home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / defaults.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-29  |  89.0 KB  |  3,457 lines

  1. /* defaults.c - manage configuration through defaults db
  2.  * 
  3.  *  Window Maker window manager
  4.  * 
  5.  *  Copyright (c) 1997, 1998 Alfredo K. Kojima
  6.  *  Copyright (c) 1998       Dan Pascu
  7.  * 
  8.  *  This program is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2 of the License, or
  11.  *  (at your option) any later version.
  12.  *
  13.  *  This program is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; if not, write to the Free Software
  20.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  21.  *  USA.
  22.  */
  23.  
  24. #include "wconfig.h"
  25. #include "plugin.h"
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <unistd.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32. #include <time.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <limits.h>
  37. #include <signal.h>
  38.  
  39. #ifdef HAVE_DLFCN_H
  40. # include <dlfcn.h>
  41. #endif
  42.  
  43.  
  44.  
  45. #ifndef PATH_MAX
  46. #define PATH_MAX DEFAULT_PATH_MAX
  47. #endif
  48.  
  49. #include <X11/Xlib.h>
  50. #include <X11/Xutil.h>
  51. #include <X11/keysym.h>
  52.  
  53. #include <wraster.h>
  54.  
  55.  
  56. #include "WindowMaker.h"
  57. #include "wcore.h"
  58. #include "framewin.h"
  59. #include "window.h"
  60. #include "texture.h"
  61. #include "screen.h"
  62. #include "resources.h"
  63. #include "defaults.h"
  64. #include "keybind.h"
  65. #include "xmodifier.h"
  66. #include "icon.h"
  67. #include "funcs.h"
  68. #include "actions.h"
  69. #include "dock.h"
  70. #include "workspace.h"
  71. #include "properties.h"
  72.  
  73.  
  74. /*
  75.  * Our own proplist reader parser. This one will not accept any
  76.  * syntax errors and is more descriptive in the error messages.
  77.  * It also doesn't seem to crash.
  78.  */
  79. extern proplist_t ReadProplistFromFile(char *file);
  80.  
  81.  
  82. /***** Global *****/
  83.  
  84. extern WDDomain *WDWindowMaker;
  85. extern WDDomain *WDWindowAttributes;
  86. extern WDDomain *WDRootMenu;
  87.  
  88. extern int wScreenCount;
  89.  
  90. extern Atom _XA_WINDOWMAKER_ICON_SIZE;
  91. extern Atom _XA_WINDOWMAKER_ICON_TILE;
  92.  
  93. /*
  94. extern proplist_t wDomainName;
  95. extern proplist_t wAttributeDomainName;
  96.  */
  97. extern WPreferences wPreferences;
  98.  
  99. extern WShortKey wKeyBindings[WKBD_LAST];
  100.  
  101. typedef struct {
  102.     char *key;
  103.     char *default_value;
  104.     void *extra_data;
  105.     void *addr;
  106.     int (*convert)();
  107.     int (*update)();
  108.     proplist_t plkey;
  109.     proplist_t plvalue;               /* default value */
  110. } WDefaultEntry;
  111.  
  112.  
  113. /* used to map strings to integers */
  114. typedef struct {
  115.     char *string;
  116.     short value;
  117.     char is_alias;
  118. } WOptionEnumeration;
  119.  
  120.  
  121. /* type converters */
  122. static int getBool();
  123. static int getInt();
  124. static int getCoord();
  125. #if 0
  126. /* this is not used yet */
  127. static int getString();
  128. #endif
  129. static int getPathList();
  130. static int getEnum();
  131. static int getTexture();
  132. #ifdef DRAWSTRING_PLUGIN
  133. static int getTextRenderer();
  134. #endif
  135. static int getWSBackground();
  136. static int getWSSpecificBackground();
  137. static int getFont();
  138. static int getColor();
  139. static int getKeybind();
  140. static int getModMask();
  141. #ifdef NEWSTUFF
  142. static int getRImage();
  143. #endif
  144.  
  145.  
  146. /* value setting functions */
  147. static int setJustify();
  148. static int setClearance();
  149. static int setIfDockPresent();
  150. static int setStickyIcons();
  151. /*
  152. static int setPositive();
  153. */
  154. static int setWidgetColor();
  155. static int setIconTile();
  156. static int setWinTitleFont();
  157. static int setMenuTitleFont();
  158. static int setMenuTextFont();
  159. static int setIconTitleFont();
  160. static int setIconTitleColor();
  161. static int setIconTitleBack();
  162. static int setLargeDisplayFont();
  163. static int setWTitleColor();
  164. static int setFTitleBack();
  165. static int setPTitleBack();
  166. static int setUTitleBack();
  167. static int setResizebarBack();
  168. static int setWorkspaceBack();
  169. static int setWorkspaceSpecificBack();
  170. static int setMenuTitleColor();
  171. static int setMenuTextColor();
  172. static int setMenuDisabledColor();
  173. static int setMenuTitleBack();
  174. static int setMenuTextBack();
  175. static int setHightlight();
  176. static int setHightlightText();
  177. static int setKeyGrab();
  178. static int setDoubleClick();
  179. static int setIconPosition();
  180.  
  181. static int setClipTitleFont();
  182. static int setClipTitleColor();
  183.  
  184. static int setMenuStyle();
  185. static int setMultiByte();
  186.  
  187. static int updateUsableArea();
  188.  
  189. #ifdef DEFINABLE_CURSOR
  190. extern Cursor wCursor[WCUR_LAST];
  191. static int getCursor();
  192. static int setCursor();
  193. #endif
  194.  
  195.  
  196. /*
  197.  * Tables to convert strings to enumeration values.
  198.  * Values stored are char
  199.  */
  200.  
  201.  
  202. /* WARNING: sum of length of all value strings must not exceed
  203.  * this value */
  204. #define TOTAL_VALUES_LENGTH    80
  205.  
  206.  
  207.  
  208.  
  209. #define REFRESH_WINDOW_TEXTURES    (1<<0)
  210. #define REFRESH_MENU_TEXTURE    (1<<1)
  211. #define REFRESH_MENU_FONT    (1<<2)
  212. #define REFRESH_MENU_COLOR    (1<<3)
  213. #define REFRESH_MENU_TITLE_TEXTURE    (1<<4)
  214. #define REFRESH_MENU_TITLE_FONT    (1<<5)
  215. #define REFRESH_MENU_TITLE_COLOR    (1<<6)
  216. #define REFRESH_WINDOW_TITLE_COLOR (1<<7)
  217. #define REFRESH_WINDOW_FONT    (1<<8)
  218. #define REFRESH_ICON_TILE    (1<<9)
  219. #define REFRESH_ICON_FONT    (1<<10)
  220. #define REFRESH_WORKSPACE_BACK    (1<<11)
  221.  
  222. #define REFRESH_BUTTON_IMAGES   (1<<12)
  223.  
  224. #define REFRESH_ICON_TITLE_COLOR (1<<13)
  225. #define REFRESH_ICON_TITLE_BACK (1<<14)
  226.  
  227.  
  228.  
  229. static WOptionEnumeration seFocusModes[] = {
  230.     {"Manual", WKF_CLICK, 0}, {"ClickToFocus", WKF_CLICK, 1},
  231.     {"Auto", WKF_POINTER, 0}, {"FocusFollowMouse", WKF_POINTER, 1},
  232.     {"Sloppy", WKF_SLOPPY, 0}, {"SemiAuto", WKF_SLOPPY, 1},
  233.     {NULL, 0, 0}
  234. };
  235.  
  236. static WOptionEnumeration seColormapModes[] = {
  237.     {"Manual", WKF_CLICK, 0}, {"ClickToFocus", WKF_CLICK, 1},
  238.     {"Auto", WKF_POINTER, 0}, {"FocusFollowMouse", WKF_POINTER, 1},
  239.     {NULL, 0, 0}
  240. };
  241.  
  242. static WOptionEnumeration sePlacements[] = {
  243.     {"Auto", WPM_AUTO, 0},
  244.     {"Smart", WPM_SMART, 0},
  245.     {"Cascade", WPM_CASCADE, 0},
  246.     {"Random", WPM_RANDOM, 0},
  247.     {"Manual", WPM_MANUAL, 0},
  248.     {NULL, 0, 0}
  249. };
  250.  
  251. static WOptionEnumeration seGeomDisplays[] = {
  252.     {"Center", WDIS_CENTER, 0},
  253.     {"Corner", WDIS_TOPLEFT, 0},
  254.     {"Floating", WDIS_FRAME_CENTER, 0},
  255.     {"Line", WDIS_NEW, 0},
  256.     {NULL, 0, 0}
  257. };
  258.  
  259. static WOptionEnumeration seSpeeds[] = {
  260.     {"UltraFast", SPEED_ULTRAFAST, 0},
  261.     {"Fast", SPEED_FAST, 0},
  262.     {"Medium", SPEED_MEDIUM, 0},
  263.     {"Slow", SPEED_SLOW, 0},
  264.     {"UltraSlow", SPEED_ULTRASLOW, 0},
  265.     {NULL, 0, 0}
  266. };
  267.  
  268. static WOptionEnumeration seMouseButtons[] = {
  269.     {"None", -1, 0},
  270.     {"Left", Button1, 0}, {"Button1", Button1, 1},
  271.     {"Middle", Button2, 0}, {"Button2", Button2, 1},
  272.     {"Right", Button3, 0}, {"Button3", Button3, 1},
  273.     {"Button4", Button4, 0},
  274.     {"Button5", Button5, 0},
  275.     {NULL, 0, 0}
  276. };
  277.  
  278. static WOptionEnumeration seIconificationStyles[] = {
  279.     {"Zoom", WIS_ZOOM, 0},
  280.     {"Twist", WIS_TWIST, 0},
  281.     {"Flip", WIS_FLIP, 0},
  282.     {"None", WIS_NONE, 0},
  283.     {"random", WIS_RANDOM, 0},
  284.     {NULL, 0, 0}
  285. };
  286.  
  287. static WOptionEnumeration seJustifications[] = {
  288.     {"Left", WTJ_LEFT, 0},
  289.     {"Center", WTJ_CENTER, 0},
  290.     {"Right", WTJ_RIGHT, 0},
  291.     {NULL, 0, 0}
  292. };
  293.  
  294. static WOptionEnumeration seIconPositions[] = {
  295.     {"blv", IY_BOTTOM|IY_LEFT|IY_VERT, 0},
  296.     {"blh", IY_BOTTOM|IY_LEFT|IY_HORIZ, 0},
  297.     {"brv", IY_BOTTOM|IY_RIGHT|IY_VERT, 0},
  298.     {"brh", IY_BOTTOM|IY_RIGHT|IY_HORIZ, 0},
  299.     {"tlv", IY_TOP|IY_LEFT|IY_VERT, 0},
  300.     {"tlh", IY_TOP|IY_LEFT|IY_HORIZ, 0},
  301.     {"trv", IY_TOP|IY_RIGHT|IY_VERT, 0},
  302.     {"trh", IY_TOP|IY_RIGHT|IY_HORIZ, 0},
  303.     {NULL, 0, 0}
  304. };
  305.  
  306. static WOptionEnumeration seMenuStyles[] = {
  307.     {"normal", MS_NORMAL, 0},
  308.     {"singletexture", MS_SINGLE_TEXTURE, 0},
  309.     {"flat", MS_FLAT, 0},
  310.     {NULL, 0, 0}
  311. };
  312.  
  313.  
  314. static WOptionEnumeration seDisplayPositions[] = {
  315.     {"none",          WD_NONE,    0},
  316.     {"center",         WD_CENTER,    0},
  317.     {"top",        WD_TOP,        0},
  318.     {"bottom",        WD_BOTTOM,    0},
  319.     {"topleft",        WD_TOPLEFT,    0},
  320.     {"topright",    WD_TOPRIGHT,     0},
  321.     {"bottomleft",    WD_BOTTOMLEFT,    0},
  322.     {"bottomright",    WD_BOTTOMRIGHT,    0}
  323. };
  324.  
  325.  
  326. /*
  327.  * ALL entries in the tables bellow, NEED to have a default value
  328.  * defined, and this value needs to be correct.
  329.  */
  330.  
  331. /* these options will only affect the window manager on startup 
  332.  *
  333.  * static defaults can't access the screen data, because it is
  334.  * created after these defaults are read
  335.  */
  336. WDefaultEntry staticOptionList[] = {    
  337.  
  338.     {"ColormapSize",    "4",            NULL,
  339.     &wPreferences.cmap_size,    getInt,        NULL
  340.     },
  341.     {"DisableDithering",    "NO",            NULL,
  342.     &wPreferences.no_dithering,    getBool,    NULL
  343.     },
  344.     /* static by laziness */
  345.     {"IconSize",    "64",            NULL,
  346.     &wPreferences.icon_size,    getInt,        NULL
  347.     },
  348.     {"ModifierKey",    "Mod1",            NULL,
  349.     &wPreferences.modifier_mask,    getModMask,    NULL
  350.     },
  351.     {"DisableWSMouseActions", "NO",        NULL,
  352.     &wPreferences.disable_root_mouse, getBool,    NULL
  353.     },
  354.     {"FocusMode",    "manual",        seFocusModes,
  355.     &wPreferences.focus_mode,    getEnum,    NULL
  356.     }, /* have a problem when switching from manual to sloppy without restart */
  357.     {"NewStyle",    "NO",            NULL,
  358.     &wPreferences.new_style,     getBool,     NULL
  359.     },
  360.     {"DisableDock",    "NO",        (void*) WM_DOCK,
  361.     NULL,     getBool,        setIfDockPresent
  362.     },
  363.     {"DisableClip",    "NO",        (void*) WM_CLIP,
  364.     NULL,     getBool,        setIfDockPresent
  365.     },
  366.     {"DisableMiniwindows", "NO",        NULL,
  367.     &wPreferences.disable_miniwindows, getBool,    NULL
  368.     },
  369.     {"MultiByteText", "NO",             NULL,
  370.     &wPreferences.multi_byte_text, getBool,        setMultiByte
  371.     }
  372. };
  373.  
  374.  
  375.  
  376. WDefaultEntry optionList[] = {
  377.       /* dynamic options */
  378.     {"IconPosition",    "blh",            seIconPositions,
  379.       &wPreferences.icon_yard,    getEnum,    setIconPosition
  380.     },
  381.     {"IconificationStyle", "Zoom",             seIconificationStyles,
  382.          &wPreferences.iconification_style,    getEnum, NULL
  383.     },
  384.     {"SelectWindowsMouseButton", "Left",    seMouseButtons,
  385.       &wPreferences.select_button,     getEnum,    NULL
  386.     },
  387.     {"WindowListMouseButton", "Middle",        seMouseButtons,
  388.       &wPreferences.windowl_button, getEnum,    NULL
  389.     },
  390.     {"ApplicationMenuMouseButton", "Right",    seMouseButtons,
  391.       &wPreferences.menu_button,    getEnum,    NULL
  392.     },
  393.     {"PixmapPath",    DEF_PIXMAP_PATHS,    NULL,
  394.       &wPreferences.pixmap_path,    getPathList,    NULL
  395.     },
  396.     {"IconPath",    DEF_ICON_PATHS,        NULL,
  397.       &wPreferences.icon_path,    getPathList,    NULL
  398.     },
  399.     {"ColormapMode",    "auto",            seColormapModes,
  400.       &wPreferences.colormap_mode,    getEnum,    NULL
  401.     },
  402.     {"AutoFocus",     "NO",            NULL,
  403.       &wPreferences.auto_focus,    getBool,    NULL
  404.     },
  405.     {"RaiseDelay",    "0",            NULL,
  406.       &wPreferences.raise_delay,    getInt,        NULL
  407.     },
  408.     {"CirculateRaise",    "NO",            NULL,
  409.       &wPreferences.circ_raise,     getBool,     NULL
  410.     },
  411.     {"Superfluous",    "NO",            NULL,
  412.       &wPreferences.superfluous,     getBool,     NULL
  413.     },
  414.     {"AdvanceToNewWorkspace", "NO",        NULL,
  415.       &wPreferences.ws_advance,      getBool,       NULL
  416.     },
  417.     {"CycleWorkspaces", "NO",            NULL,
  418.       &wPreferences.ws_cycle,        getBool,    NULL
  419.     },
  420.     {"WorkspaceNameDisplayPosition", "center",    seDisplayPositions,
  421.       &wPreferences.workspace_name_display_position, getEnum, NULL
  422.     },
  423. #ifdef VIRTUAL_DESKTOP
  424.     {"VirtualEdgeThickness", "1",   NULL,
  425.         &wPreferences.vedge_thickness, getInt,        NULL
  426.     },
  427.     {"VirtualEdgeHorizonScrollSpeed", "1",  NULL,
  428.         &wPreferences.vedge_hscrollspeed, getInt,     NULL
  429.     },
  430.     {"VirtualEdgeVerticalScrollSpeed", "1", NULL,
  431.         &wPreferences.vedge_vscrollspeed, getInt,     NULL
  432.     },
  433.     {"VirtualEdgeWidth", "2000",    NULL,
  434.         &wPreferences.vedge_width, getInt,        NULL
  435.     },
  436.     {"VirtualEdgeHeight", "2000",   NULL,
  437.         &wPreferences.vedge_height, getInt,       NULL
  438.     },
  439. #endif
  440.     {"StickyIcons", "NO",            NULL,
  441.       &wPreferences.sticky_icons, getBool, setStickyIcons
  442.     },
  443.     {"SaveSessionOnExit", "NO",            NULL,
  444.       &wPreferences.save_session_on_exit, getBool,    NULL
  445.     },
  446.     {"WrapMenus", "NO",                NULL,
  447.       &wPreferences.wrap_menus,    getBool,    NULL
  448.     },
  449.     {"ScrollableMenus",    "NO",            NULL,
  450.       &wPreferences.scrollable_menus, getBool,    NULL
  451.     },
  452.     {"MenuScrollSpeed",    "medium",            seSpeeds,
  453.       &wPreferences.menu_scroll_speed, getEnum,        NULL
  454.     },
  455.     {"IconSlideSpeed",    "medium",        seSpeeds,
  456.       &wPreferences.icon_slide_speed, getEnum,         NULL
  457.     },
  458.     {"ShadeSpeed",    "medium",            seSpeeds,
  459.       &wPreferences.shade_speed,     getEnum,    NULL
  460.     },
  461.     {"DoubleClickTime",    "250",   (void*) &wPreferences.dblclick_time,
  462.       &wPreferences.dblclick_time, getInt,        setDoubleClick,
  463.     },
  464.     {"AlignSubmenus",    "NO",            NULL,
  465.       &wPreferences.align_menus,    getBool,    NULL
  466.     },
  467.     {"OpenTransientOnOwnerWorkspace",    "NO",    NULL,
  468.       &wPreferences.open_transients_with_parent, getBool,    NULL
  469.     },
  470.     {"WindowPlacement",    "auto",        sePlacements,
  471.       &wPreferences.window_placement, getEnum,    NULL
  472.     },
  473.     {"IgnoreFocusClick","NO",            NULL,
  474.       &wPreferences.ignore_focus_click, getBool,    NULL
  475.     },
  476.     {"UseSaveUnders",    "NO",            NULL,
  477.       &wPreferences.use_saveunders,    getBool,    NULL
  478.     },
  479.     {"OpaqueMove",    "NO",            NULL,
  480.       &wPreferences.opaque_move,    getBool,    NULL
  481.     },
  482.     {"DisableSound",    "NO",            NULL,
  483.       &wPreferences.no_sound,    getBool,    NULL
  484.     },
  485.     {"DisableAnimations",    "NO",            NULL,
  486.       &wPreferences.no_animations,    getBool,    NULL
  487.     },
  488.     {"DontLinkWorkspaces","NO",            NULL,
  489.       &wPreferences.no_autowrap,    getBool,    NULL
  490.     },
  491.     {"AutoArrangeIcons", "NO",            NULL,
  492.       &wPreferences.auto_arrange_icons, getBool,    NULL
  493.     },
  494.     {"NoWindowOverDock", "NO",            NULL,
  495.       &wPreferences.no_window_over_dock, getBool,   updateUsableArea
  496.     },
  497.     {"NoWindowOverIcons", "NO",            NULL,
  498.       &wPreferences.no_window_over_icons, getBool,  updateUsableArea
  499.     },
  500.     {"WindowPlaceOrigin", "(0, 0)",        NULL,
  501.       &wPreferences.window_place_origin, getCoord,  NULL
  502.     },
  503.     {"ResizeDisplay",    "corner",               seGeomDisplays,
  504.       &wPreferences.size_display,    getEnum,    NULL
  505.     },
  506.     {"MoveDisplay",    "corner",              seGeomDisplays,
  507.       &wPreferences.move_display,    getEnum,    NULL
  508.     },
  509.     {"DontConfirmKill",    "NO",            NULL,
  510.       &wPreferences.dont_confirm_kill,    getBool,NULL
  511.     },
  512.     {"WindowTitleBalloons", "NO",        NULL,
  513.       &wPreferences.window_balloon,    getBool,    NULL
  514.     },
  515.     {"MiniwindowTitleBalloons", "NO",        NULL,
  516.       &wPreferences.miniwin_balloon,getBool,    NULL
  517.     },
  518.     {"AppIconBalloons", "NO",        NULL,
  519.       &wPreferences.appicon_balloon,getBool,    NULL
  520.     },
  521.     {"HelpBalloons",    "NO",        NULL,
  522.       &wPreferences.help_balloon,    getBool,    NULL
  523.     },
  524.     {"EdgeResistance",     "30",            NULL,
  525.       &wPreferences.edge_resistance,getInt,        NULL
  526.     },
  527.     {"Attraction",     "NO",            NULL,
  528.       &wPreferences.attract,  getBool,    NULL
  529.     },
  530.     {"DisableBlinking",    "NO",        NULL,
  531.        &wPreferences.dont_blink,    getBool,    NULL
  532.     },
  533.       /* style options */
  534.     {"MenuStyle",     "normal",          seMenuStyles,
  535.     &wPreferences.menu_style, getEnum,     setMenuStyle
  536.     },
  537.     {"WidgetColor",    "(solid, gray)",    NULL,
  538.       NULL,                getTexture,    setWidgetColor,
  539.     },
  540.     {"WorkspaceSpecificBack","()",    NULL,
  541.       NULL,        getWSSpecificBackground, setWorkspaceSpecificBack
  542.     },
  543.     /* WorkspaceBack must come after WorkspaceSpecificBack or
  544.      * WorkspaceBack wont know WorkspaceSpecificBack was also
  545.      * specified and 2 copies of wmsetbg will be launched */
  546.     {"WorkspaceBack",    "(solid, black)",    NULL,
  547.       NULL,                getWSBackground,setWorkspaceBack
  548.     },
  549.     {"SmoothWorkspaceBack",     "NO",        NULL,
  550.       NULL,                getBool,    NULL
  551.     },
  552.     {"IconBack",    "(solid, gray)",           NULL,
  553.       NULL,                getTexture,    setIconTile
  554.     },
  555.     {"TitleJustify",    "center",        seJustifications,
  556.       &wPreferences.title_justification, getEnum,    setJustify
  557.     },
  558.     {"WindowTitleFont",    DEF_TITLE_FONT,               NULL,
  559.       NULL,                getFont,    setWinTitleFont,
  560.     },
  561.     {"WindowTitleExtendSpace",    DEF_WINDOW_TITLE_EXTEND_SPACE,               NULL,
  562.       &wPreferences.window_title_clearance,    getInt,        setClearance
  563.     },
  564.     {"MenuTitleExtendSpace",    DEF_MENU_TITLE_EXTEND_SPACE,               NULL,
  565.       &wPreferences.menu_title_clearance,    getInt,        setClearance
  566.     },
  567.     {"MenuTextExtendSpace",    DEF_MENU_TEXT_EXTEND_SPACE,               NULL,
  568.       &wPreferences.menu_text_clearance,    getInt,        setClearance
  569.     },
  570.     {"MenuTitleFont",    DEF_MENU_TITLE_FONT,    NULL,
  571.       NULL,                getFont,    setMenuTitleFont
  572.     },
  573.     {"MenuTextFont",    DEF_MENU_ENTRY_FONT,    NULL,
  574.       NULL,                getFont,    setMenuTextFont
  575.     },
  576.     {"IconTitleFont",    DEF_ICON_TITLE_FONT,    NULL,
  577.       NULL,                getFont,    setIconTitleFont
  578.     },
  579.     {"ClipTitleFont",    DEF_CLIP_TITLE_FONT,    NULL,
  580.       NULL,                getFont,    setClipTitleFont
  581.     },
  582.     {"LargeDisplayFont",DEF_WORKSPACE_NAME_FONT, NULL,
  583.       NULL,                getFont,    setLargeDisplayFont
  584.     },
  585.     {"HighlightColor",    "white",        NULL,
  586.       NULL,                getColor,    setHightlight
  587.     },
  588.     {"HighlightTextColor",    "black",    NULL,
  589.       NULL,                getColor,    setHightlightText
  590.     },
  591.     {"ClipTitleColor",    "black",        (void*)CLIP_NORMAL,
  592.       NULL,                getColor,    setClipTitleColor
  593.     },
  594.     {"CClipTitleColor", "\"#454045\"",        (void*)CLIP_COLLAPSED,
  595.       NULL,                getColor,    setClipTitleColor
  596.     },
  597. #ifdef DRAWSTRING_PLUGIN
  598.     {"FTitleColor",    "white",             (void*)WS_FOCUSED,
  599.          NULL,          getTextRenderer,    setWTitleColor
  600.     },
  601.     {"PTitleColor",    "white",             (void*)WS_PFOCUSED,
  602.          NULL,          getTextRenderer,    setWTitleColor
  603.     },
  604.     {"UTitleColor",    "black",             (void*)WS_UNFOCUSED,
  605.          NULL,          getTextRenderer,    setWTitleColor
  606.     },
  607. #else
  608.     {"FTitleColor",    "white",        (void*)WS_FOCUSED,
  609.       NULL,                getColor,    setWTitleColor
  610.     },
  611.     {"PTitleColor",    "white",        (void*)WS_PFOCUSED,
  612.       NULL,                getColor,    setWTitleColor
  613.     },
  614.     {"UTitleColor",    "black",        (void*)WS_UNFOCUSED,
  615.       NULL,                getColor,    setWTitleColor
  616.     },
  617. #endif
  618.     {"FTitleBack",    "(solid, black)",          NULL,
  619.       NULL,                getTexture,    setFTitleBack
  620.     },
  621.     {"PTitleBack",    "(solid, \"#616161\")",    NULL,
  622.       NULL,                getTexture,    setPTitleBack
  623.     },
  624.     {"UTitleBack",    "(solid, gray)",    NULL,
  625.       NULL,                getTexture,    setUTitleBack
  626.     },
  627.     {"ResizebarBack",    "(solid, gray)",    NULL,
  628.       NULL,                getTexture,    setResizebarBack
  629.     },
  630. #ifdef DRAWSTRING_PLUGIN
  631.     {"MenuTitleColor", "white",             NULL,
  632.         NULL,           getTextRenderer,    setMenuTitleColor
  633.     },
  634. #else
  635.     {"MenuTitleColor",    "white",               NULL,
  636.       NULL,                getColor,    setMenuTitleColor
  637.     },
  638. #endif
  639.     {"MenuTextColor",    "black",               NULL,
  640.       NULL,                getColor,    setMenuTextColor
  641.     },
  642.     {"MenuDisabledColor", "\"#616161\"",           NULL,
  643.       NULL,                getColor,    setMenuDisabledColor
  644.     },
  645.     {"MenuTitleBack",    "(solid, black)",          NULL,
  646.       NULL,                getTexture,    setMenuTitleBack
  647.     },
  648.     {"MenuTextBack",    "(solid, gray)",           NULL,
  649.       NULL,                getTexture,    setMenuTextBack
  650.     },
  651.     {"IconTitleColor",    "white",               NULL,
  652.       NULL,                getColor,    setIconTitleColor
  653.     },
  654.     {"IconTitleBack",    "black",               NULL,
  655.       NULL,                getColor,    setIconTitleBack
  656.     },
  657.     /* keybindings */
  658. #ifndef LITE
  659.     {"RootMenuKey",    "None",            (void*)WKBD_ROOTMENU,
  660.       NULL,                getKeybind,    setKeyGrab
  661.     },
  662.     {"WindowListKey",    "None",            (void*)WKBD_WINDOWLIST,
  663.       NULL,                getKeybind,    setKeyGrab
  664.     },
  665. #endif /* LITE */
  666.     {"WindowMenuKey",    "None",                   (void*)WKBD_WINDOWMENU,
  667.       NULL,                getKeybind,    setKeyGrab
  668.     },
  669.     {"ClipLowerKey",   "None",                (void*)WKBD_CLIPLOWER,
  670.       NULL,                getKeybind,    setKeyGrab
  671.     },
  672.     {"ClipRaiseKey",   "None",                (void*)WKBD_CLIPRAISE,
  673.       NULL,                getKeybind,    setKeyGrab
  674.     },
  675.     {"ClipRaiseLowerKey", "None",         (void*)WKBD_CLIPRAISELOWER,
  676.       NULL,                getKeybind,    setKeyGrab
  677.     },
  678.     {"MiniaturizeKey",    "None",                   (void*)WKBD_MINIATURIZE,
  679.       NULL,                getKeybind,    setKeyGrab
  680.     },
  681.     {"HideKey", "None",                       (void*)WKBD_HIDE,
  682.       NULL,                getKeybind,    setKeyGrab
  683.     },
  684.     {"MoveResizeKey", "None",                   (void*)WKBD_MOVERESIZE,
  685.       NULL,                getKeybind,    setKeyGrab
  686.     },
  687.     {"CloseKey", "None",                   (void*)WKBD_CLOSE,
  688.       NULL,                getKeybind,    setKeyGrab
  689.     },
  690.     {"MaximizeKey", "None",            (void*)WKBD_MAXIMIZE,
  691.       NULL,                getKeybind,    setKeyGrab
  692.     },
  693.     {"VMaximizeKey", "None",            (void*)WKBD_VMAXIMIZE,
  694.       NULL,                getKeybind,    setKeyGrab
  695.     },
  696.     {"RaiseKey", "\"Meta+Up\"",            (void*)WKBD_RAISE,
  697.       NULL,                getKeybind,    setKeyGrab
  698.     },
  699.     {"LowerKey", "\"Meta+Down\"",            (void*)WKBD_LOWER,
  700.       NULL,                getKeybind,    setKeyGrab
  701.     },
  702.     {"RaiseLowerKey", "None",            (void*)WKBD_RAISELOWER,
  703.       NULL,                getKeybind,    setKeyGrab
  704.     },
  705.     {"ShadeKey", "None",            (void*)WKBD_SHADE,
  706.       NULL,                getKeybind,    setKeyGrab
  707.     },
  708.     {"SelectKey", "None",            (void*)WKBD_SELECT,
  709.       NULL,                getKeybind,    setKeyGrab
  710.     },
  711.     {"FocusNextKey", "None",                   (void*)WKBD_FOCUSNEXT,
  712.       NULL,                getKeybind,    setKeyGrab
  713.     },
  714.     {"FocusPrevKey", "None",            (void*)WKBD_FOCUSPREV,
  715.       NULL,                getKeybind,    setKeyGrab
  716.     },
  717.     {"NextWorkspaceKey", "None",        (void*)WKBD_NEXTWORKSPACE,
  718.       NULL,                getKeybind,    setKeyGrab
  719.     },
  720.     {"PrevWorkspaceKey", "None",               (void*)WKBD_PREVWORKSPACE,
  721.       NULL,                getKeybind,    setKeyGrab
  722.     },
  723.     {"NextWorkspaceLayerKey", "None",        (void*)WKBD_NEXTWSLAYER,
  724.       NULL,                getKeybind,    setKeyGrab
  725.     },
  726.     {"PrevWorkspaceLayerKey", "None",         (void*)WKBD_PREVWSLAYER,
  727.       NULL,                getKeybind,    setKeyGrab
  728.     },
  729.     {"Workspace1Key", "None",            (void*)WKBD_WORKSPACE1,
  730.       NULL,                getKeybind,    setKeyGrab
  731.     },
  732.     {"Workspace2Key", "None",            (void*)WKBD_WORKSPACE2,
  733.       NULL,                getKeybind,    setKeyGrab
  734.     },
  735.     {"Workspace3Key", "None",            (void*)WKBD_WORKSPACE3,
  736.       NULL,                getKeybind,    setKeyGrab
  737.     },
  738.     {"Workspace4Key", "None",            (void*)WKBD_WORKSPACE4,
  739.       NULL,                getKeybind,    setKeyGrab
  740.     },
  741.     {"Workspace5Key", "None",            (void*)WKBD_WORKSPACE5,
  742.       NULL,                getKeybind,    setKeyGrab
  743.     },
  744.     {"Workspace6Key", "None",            (void*)WKBD_WORKSPACE6,
  745.       NULL,                getKeybind,    setKeyGrab
  746.     },
  747.     {"Workspace7Key", "None",            (void*)WKBD_WORKSPACE7,
  748.       NULL,                getKeybind,    setKeyGrab
  749.     },
  750.     {"Workspace8Key", "None",            (void*)WKBD_WORKSPACE8,
  751.       NULL,                getKeybind,    setKeyGrab
  752.     },
  753.     {"Workspace9Key", "None",            (void*)WKBD_WORKSPACE9,
  754.       NULL,                getKeybind,    setKeyGrab
  755.     },
  756.     {"Workspace10Key", "None",            (void*)WKBD_WORKSPACE10,
  757.       NULL,                getKeybind,    setKeyGrab
  758.     },
  759.     {"WindowShortcut1Key","None",        (void*)WKBD_WINDOW1,
  760.         NULL,             getKeybind,    setKeyGrab
  761.     },
  762.     {"WindowShortcut2Key","None",        (void*)WKBD_WINDOW2,
  763.         NULL,             getKeybind,    setKeyGrab
  764.     },
  765.     {"WindowShortcut3Key","None",        (void*)WKBD_WINDOW3,
  766.         NULL,             getKeybind,    setKeyGrab
  767.     },
  768.     {"WindowShortcut4Key","None",        (void*)WKBD_WINDOW4,
  769.         NULL,             getKeybind,    setKeyGrab
  770.     }
  771. #ifdef EXTEND_WINDOWSHORTCUT
  772.     ,{"WindowShortcut5Key","None",        (void*)WKBD_WINDOW5,
  773.         NULL,             getKeybind,    setKeyGrab
  774.     },
  775.     {"WindowShortcut6Key","None",        (void*)WKBD_WINDOW6,
  776.         NULL,             getKeybind,    setKeyGrab
  777.     },
  778.     {"WindowShortcut7Key","None",        (void*)WKBD_WINDOW7,
  779.         NULL,             getKeybind,    setKeyGrab
  780.     },
  781.     {"WindowShortcut8Key","None",        (void*)WKBD_WINDOW8,
  782.         NULL,             getKeybind,    setKeyGrab
  783.     },
  784.     {"WindowShortcut9Key","None",        (void*)WKBD_WINDOW9,
  785.         NULL,             getKeybind,    setKeyGrab
  786.     },
  787.     {"WindowShortcut10Key","None",        (void*)WKBD_WINDOW10,
  788.         NULL,             getKeybind,    setKeyGrab
  789.     }
  790. #endif /* EXTEND_WINDOWSHORTCUT */
  791.  
  792. #ifdef KEEP_XKB_LOCK_STATUS
  793.     ,{"ToggleKbdModeKey", "None",                      (void*)WKBD_TOGGLE,
  794.         NULL,                       getKeybind,     setKeyGrab
  795.     },
  796.     {"KbdModeLock", "NO",                        NULL,
  797.         &wPreferences.modelock,     getBool,    NULL
  798.     }
  799. #endif /* KEEP_XKB_LOCK_STATUS */
  800. #ifdef DEFINABLE_CURSOR
  801.     ,{"NormalCursor", "(builtin, left_ptr)",    (void*)WCUR_ROOT,
  802.           NULL,                getCursor,    setCursor
  803.     }
  804.     ,{"MoveCursor", "(builtin, fleur)",        (void*)WCUR_MOVE,
  805.           NULL,                getCursor,    setCursor
  806.     },
  807. #if 0
  808.     {"TopLeftResizeCursor", "(builtin, sizing)",    (void*)WCUR_TOPLEFTRESIZE,
  809.           NULL,                getCursor,    setCursor
  810.     },
  811.     {"TopRightResizeCursor", "(builtin, sizing)",    (void*)WCUR_TOPRIGHTRESIZE,
  812.           NULL,                getCursor,    setCursor
  813.     },
  814.     {"BottomLeftResizeCursor", "(builtin, sizing)",    (void*)WCUR_BOTTOMLEFTRESIZE,
  815.           NULL,                getCursor,    setCursor
  816.     },
  817.     {"BottomRightResizeCursor", "(builtin, sizing)",    (void*)WCUR_BOTTOMRIGHTRESIZE,
  818.           NULL,                getCursor,    setCursor
  819.     },
  820.     {"VerticalResizeCursor", "(builtin, sizing)",    (void*)WCUR_VERTICALRESIZE,
  821.           NULL,                getCursor,    setCursor
  822.     },
  823.     {"HorizonResizeCursor", "(builtin, sizing)",    (void*)WCUR_HORIZONRESIZE,
  824.           NULL,                getCursor,    setCursor
  825.     },
  826.     {"WaitCursor", "(builtin, watch)",        (void*)WCUR_WAIT,
  827.           NULL,                getCursor,    setCursor
  828.     }
  829.     ,{"ArrowCursor", "(builtin, top_left_arrow)",    (void*)WCUR_ARROW,
  830.           NULL,                getCursor,    setCursor
  831.     }
  832.     ,{"QuestionCursor", "(builtin, question_arrow)",    (void*)WCUR_QUESTION,
  833.           NULL,                getCursor,    setCursor
  834.     }
  835.     ,{"TextCursor", "(builtin, xterm)",        (void*)WCUR_TEXT,
  836.           NULL,                getCursor,    setCursor
  837.     }
  838. #endif
  839. #endif /* DEFINABLE_CURSOR */
  840. };
  841.  
  842.  
  843. #if 0
  844. static void rereadDefaults(void);
  845. #endif
  846.  
  847. #if 0
  848. static void
  849. rereadDefaults(void)
  850. {
  851.     /* must defer the update because accessing X data from a
  852.      * signal handler can mess up Xlib */
  853.     
  854. }
  855. #endif
  856.  
  857. static void
  858. initDefaults()
  859. {
  860.     int i;
  861.     WDefaultEntry *entry;
  862.  
  863.     PLSetStringCmpHook(StringCompareHook);
  864.  
  865.     for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
  866.     entry = &optionList[i];
  867.  
  868.     entry->plkey = PLMakeString(entry->key);
  869.     if (entry->default_value)
  870.         entry->plvalue = PLGetProplistWithDescription(entry->default_value);
  871.     else
  872.         entry->plvalue = NULL;
  873.     }
  874.  
  875.     for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
  876.     entry = &staticOptionList[i];
  877.     
  878.     entry->plkey = PLMakeString(entry->key);
  879.     if (entry->default_value)
  880.         entry->plvalue = PLGetProplistWithDescription(entry->default_value);
  881.     else
  882.         entry->plvalue = NULL;
  883.     }
  884.         
  885. /*
  886.     wDomainName = PLMakeString(WMDOMAIN_NAME);
  887.     wAttributeDomainName = PLMakeString(WMATTRIBUTE_DOMAIN_NAME);
  888.  
  889.     PLRegister(wDomainName, rereadDefaults);
  890.     PLRegister(wAttributeDomainName, rereadDefaults);
  891.  */
  892. }
  893.  
  894.  
  895.  
  896.  
  897. #if 0
  898. proplist_t
  899. wDefaultsInit(int screen_number)
  900. {
  901.     static int defaults_inited = 0;
  902.     proplist_t dict;
  903.     
  904.     if (!defaults_inited) {
  905.     initDefaults();
  906.     }
  907.     
  908.     dict = PLGetDomain(wDomainName);
  909.     if (!dict) {
  910.     wwarning(_("could not read domain \"%s\" from defaults database"),
  911.          PLGetString(wDomainName));
  912.     }
  913.  
  914.     return dict;
  915. }
  916. #endif
  917.  
  918.  
  919. void
  920. wDefaultsDestroyDomain(WDDomain *domain)
  921. {
  922.     if (domain->dictionary)
  923.     PLRelease(domain->dictionary);
  924.     free(domain->path);
  925.     free(domain);
  926. }
  927.  
  928.  
  929. WDDomain*
  930. wDefaultsInitDomain(char *domain, Bool requireDictionary)
  931. {
  932.     WDDomain *db;
  933.     struct stat stbuf;
  934.     static int inited = 0;
  935.     char path[PATH_MAX];
  936.     char *the_path;
  937.     proplist_t shared_dict=NULL;
  938.  
  939.     if (!inited) {
  940.     inited = 1;
  941.     initDefaults();
  942.     }
  943.  
  944.     db = wmalloc(sizeof(WDDomain));
  945.     memset(db, 0, sizeof(WDDomain));
  946.     db->domain_name = domain;
  947.     db->path = wdefaultspathfordomain(domain);
  948.     the_path = db->path;
  949.     
  950.     if (the_path && stat(the_path, &stbuf)>=0) {
  951.     db->dictionary = ReadProplistFromFile(the_path);
  952.     if (db->dictionary) {
  953.         if (requireDictionary && !PLIsDictionary(db->dictionary)) {
  954.         PLRelease(db->dictionary);
  955.         db->dictionary = NULL;
  956.         wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
  957.              domain, the_path);
  958.         }
  959.         db->timestamp = stbuf.st_mtime;
  960.     } else {
  961.         wwarning(_("could not load domain %s from user defaults database"),
  962.              domain);
  963.     }
  964.     }
  965.  
  966.     /* global system dictionary */
  967.     sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
  968.     if (stat(path, &stbuf)>=0) {
  969.         shared_dict = ReadProplistFromFile(path);
  970.         if (shared_dict) {
  971.         if (requireDictionary && !PLIsDictionary(shared_dict)) {
  972.         wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
  973.              domain, path);
  974.         PLRelease(shared_dict);
  975.         shared_dict = NULL;
  976.         } else {
  977.         if (db->dictionary && PLIsDictionary(shared_dict) &&
  978.             PLIsDictionary(db->dictionary)) {
  979.             PLMergeDictionaries(shared_dict, db->dictionary);
  980.             PLRelease(db->dictionary);
  981.             db->dictionary = shared_dict;
  982.             if (stbuf.st_mtime > db->timestamp)
  983.             db->timestamp = stbuf.st_mtime;
  984.         } else if (!db->dictionary) {
  985.             db->dictionary = shared_dict;
  986.             if (stbuf.st_mtime > db->timestamp)
  987.             db->timestamp = stbuf.st_mtime;
  988.         }
  989.             }
  990.         } else {
  991.         wwarning(_("could not load domain %s from global defaults database (%s)"),
  992.              domain, path);
  993.     }
  994.     }
  995.  
  996.     /* set to save it in user's directory, no matter from where it was read */
  997.     if (db->dictionary) {
  998.         proplist_t tmp = PLMakeString(db->path);
  999.  
  1000.         PLSetFilename(db->dictionary, tmp);
  1001.         PLRelease(tmp);
  1002.     }
  1003.  
  1004.     return db;
  1005. }
  1006.  
  1007.  
  1008. void
  1009. wReadStaticDefaults(proplist_t dict)
  1010. {
  1011.     proplist_t plvalue;
  1012.     WDefaultEntry *entry;
  1013.     int i;
  1014.     void *tdata;
  1015.  
  1016.     
  1017.     for (i=0; i<sizeof(staticOptionList)/sizeof(WDefaultEntry); i++) {
  1018.     entry = &staticOptionList[i];
  1019.  
  1020.     if (dict)
  1021.       plvalue = PLGetDictionaryEntry(dict, entry->plkey);
  1022.     else
  1023.       plvalue = NULL;
  1024.     
  1025.     if (!plvalue) {
  1026.         /* no default in the DB. Use builtin default */
  1027.         plvalue = entry->plvalue;
  1028.     }
  1029.     
  1030.     if (plvalue) {
  1031.         /* convert data */
  1032.         (*entry->convert)(NULL, entry, plvalue, entry->addr, &tdata);
  1033.             if (entry->update) {
  1034.                 (*entry->update)(NULL, entry, tdata, entry->extra_data);
  1035.             }
  1036.     }
  1037.     }
  1038. }
  1039.  
  1040.  
  1041. void
  1042. wDefaultsCheckDomains(void *foo)
  1043. {
  1044.     WScreen *scr;
  1045.     struct stat stbuf;
  1046.     proplist_t dict;
  1047.     int i;
  1048.     char path[PATH_MAX];
  1049.  
  1050. #ifdef HEARTBEAT
  1051.     puts("Checking domains...");
  1052. #endif
  1053.     if (stat(WDWindowMaker->path, &stbuf)>=0
  1054.     && WDWindowMaker->timestamp < stbuf.st_mtime) {
  1055.     proplist_t shared_dict = NULL;
  1056. #ifdef HEARTBEAT
  1057.     puts("Checking WindowMaker domain");
  1058. #endif
  1059.     WDWindowMaker->timestamp = stbuf.st_mtime;    
  1060.  
  1061.     /* global dictionary */
  1062.     sprintf(path, "%s/WindowMaker/WindowMaker", SYSCONFDIR);
  1063.     if (stat(path, &stbuf)>=0) {
  1064.         shared_dict = ReadProplistFromFile(path);
  1065.         if (shared_dict && !PLIsDictionary(shared_dict)) {
  1066.         wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
  1067.              "WindowMaker", path);
  1068.         PLRelease(shared_dict);
  1069.         shared_dict = NULL;
  1070.         } else if (!shared_dict) {
  1071.         wwarning(_("could not load domain %s from global defaults database"),
  1072.              "WindowMaker");
  1073.         }
  1074.     }
  1075.     /* user dictionary */
  1076.     dict = ReadProplistFromFile(WDWindowMaker->path);
  1077.     if (dict) {
  1078.         if (!PLIsDictionary(dict)) {
  1079.         PLRelease(dict);
  1080.         dict = NULL;
  1081.         wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
  1082.              "WindowMaker", WDWindowMaker->path);
  1083.         } else {
  1084.         if (shared_dict) {
  1085.             PLSetFilename(shared_dict, PLGetFilename(dict));
  1086.             PLMergeDictionaries(shared_dict, dict);
  1087.             PLRelease(dict);
  1088.             dict = shared_dict;
  1089.             shared_dict = NULL;
  1090.         }
  1091.         for (i=0; i<wScreenCount; i++) {
  1092.             scr = wScreenWithNumber(i);
  1093.             if (scr)
  1094.             wReadDefaults(scr, dict);
  1095.         }
  1096.         if (WDWindowMaker->dictionary) {
  1097.             PLRelease(WDWindowMaker->dictionary);
  1098.         }
  1099.         WDWindowMaker->dictionary = dict;
  1100.         }
  1101.     } else {
  1102.         wwarning(_("could not load domain %s from user defaults database"),
  1103.              "WindowMaker");
  1104.     }
  1105.     if (shared_dict) {
  1106.         PLRelease(shared_dict);
  1107.     }
  1108.     }
  1109.  
  1110.     if (stat(WDWindowAttributes->path, &stbuf)>=0
  1111.     && WDWindowAttributes->timestamp < stbuf.st_mtime) {
  1112. #ifdef HEARTBEAT
  1113.     puts("Checking WMWindowAttributes domain");
  1114. #endif
  1115.     dict = ReadProplistFromFile(WDWindowAttributes->path);
  1116.     if (dict) {
  1117.         if (!PLIsDictionary(dict)) {
  1118.         PLRelease(dict);
  1119.         dict = NULL;
  1120.         wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
  1121.              "WMWindowAttributes", WDWindowAttributes->path);
  1122.         } else {
  1123.         if (WDWindowAttributes->dictionary)
  1124.             PLRelease(WDWindowAttributes->dictionary);
  1125.         WDWindowAttributes->dictionary = dict;
  1126.         for (i=0; i<wScreenCount; i++) {
  1127.             scr = wScreenWithNumber(i);
  1128.             if (scr)
  1129.             wDefaultUpdateIcons(scr);
  1130.         }
  1131.         }
  1132.     } else {
  1133.         wwarning(_("could not load domain %s from user defaults database"),
  1134.              "WMWindowAttributes");
  1135.     }
  1136.     WDWindowAttributes->timestamp = stbuf.st_mtime;
  1137.     }
  1138.  
  1139. #ifndef LITE
  1140.     if (stat(WDRootMenu->path, &stbuf)>=0
  1141.     && WDRootMenu->timestamp < stbuf.st_mtime) {
  1142.     dict = ReadProplistFromFile(WDRootMenu->path);
  1143. #ifdef HEARTBEAT
  1144.     puts("Checking WMRootMenu domain");
  1145. #endif
  1146.     if (dict) {
  1147.         if (!PLIsArray(dict) && !PLIsString(dict)) {
  1148.         PLRelease(dict);
  1149.         dict = NULL;
  1150.         wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
  1151.              "WMRootMenu", WDRootMenu->path);
  1152.         } else {
  1153.         if (WDRootMenu->dictionary) {
  1154.             PLRelease(WDRootMenu->dictionary);
  1155.         }
  1156.         WDRootMenu->dictionary = dict;
  1157.         }
  1158.     } else {
  1159.         wwarning(_("could not load domain %s from user defaults database"),
  1160.              "WMRootMenu");
  1161.     }
  1162.     WDRootMenu->timestamp = stbuf.st_mtime;
  1163.     }
  1164. #endif /* !LITE */
  1165.  
  1166.     if (!foo)
  1167.     WMAddTimerHandler(DEFAULTS_CHECK_INTERVAL, wDefaultsCheckDomains, foo);
  1168. }
  1169.  
  1170.  
  1171. void
  1172. wReadDefaults(WScreen *scr, proplist_t new_dict)
  1173. {
  1174.     proplist_t plvalue, old_value;
  1175.     WDefaultEntry *entry;
  1176.     int i, must_update;
  1177.     int update_workspace_back = 0;           /* kluge :/ */
  1178.     int needs_refresh;
  1179.     void *tdata;
  1180.     proplist_t old_dict = (WDWindowMaker->dictionary!=new_dict 
  1181.                ? WDWindowMaker->dictionary : NULL);
  1182.     
  1183.     must_update = 0;
  1184.     
  1185.     needs_refresh = 0;
  1186.     
  1187.     for (i=0; i<sizeof(optionList)/sizeof(WDefaultEntry); i++) {
  1188.     entry = &optionList[i];
  1189.     
  1190.     if (new_dict)
  1191.         plvalue = PLGetDictionaryEntry(new_dict, entry->plkey);
  1192.     else
  1193.         plvalue = NULL;
  1194.  
  1195.     if (!old_dict)
  1196.         old_value = NULL;
  1197.     else
  1198.         old_value = PLGetDictionaryEntry(old_dict, entry->plkey);
  1199.  
  1200.     
  1201.     if (!plvalue && !old_value) {
  1202.         /* no default in  the DB. Use builtin default */
  1203.         plvalue = entry->plvalue;
  1204.         if (plvalue && new_dict) {
  1205.         PLInsertDictionaryEntry(new_dict, entry->plkey, plvalue);
  1206.         must_update = 1;
  1207.         }
  1208.     } else if (!plvalue) {
  1209.         /* value was deleted from DB. Keep current value */
  1210.         continue;
  1211.     } else if (!old_value) {
  1212.         /* set value for the 1st time */
  1213.     } else if (!PLIsEqual(plvalue, old_value)) {        
  1214.         /* value has changed */
  1215.     } else {
  1216.         
  1217.         if (strcmp(entry->key, "WorkspaceBack") == 0
  1218.         && update_workspace_back
  1219.         && scr->flags.backimage_helper_launched) {
  1220.         } else {
  1221.         /* value was not changed since last time */
  1222.         continue;
  1223.         }
  1224.     }
  1225.     
  1226.     if (plvalue) {
  1227. #ifdef DEBUG
  1228.         printf("Updating %s to %s\n", entry->key, 
  1229.            PLGetDescription(plvalue));
  1230. #endif
  1231.         /* convert data */
  1232.         if ((*entry->convert)(scr, entry, plvalue, entry->addr, &tdata)) {
  1233.         /*
  1234.          * If the WorkspaceSpecificBack data has been changed
  1235.          * so that the helper will be launched now, we must be
  1236.          * sure to send the default background texture config
  1237.          * to the helper.
  1238.          */
  1239.         if (strcmp(entry->key, "WorkspaceSpecificBack") == 0
  1240.             && !scr->flags.backimage_helper_launched) {
  1241.             update_workspace_back = 1;
  1242.         }
  1243.         if (entry->update) {
  1244.             needs_refresh |= 
  1245.             (*entry->update)(scr, entry, tdata, entry->extra_data);
  1246.         }
  1247.         }
  1248.     }
  1249.     }
  1250.  
  1251.     if (needs_refresh!=0 && !scr->flags.startup) {
  1252.     int foo;
  1253.  
  1254.     foo = 0;
  1255.     if (needs_refresh & REFRESH_MENU_TITLE_TEXTURE)
  1256.         foo |= WTextureSettings;
  1257.     if (needs_refresh & REFRESH_MENU_TITLE_FONT)
  1258.         foo |= WFontSettings;
  1259.     if (needs_refresh & REFRESH_MENU_TITLE_COLOR)
  1260.         foo |= WColorSettings;
  1261.         if (foo)
  1262.         WMPostNotificationName(WNMenuTitleAppearanceSettingsChanged, NULL,
  1263.                    (void*)foo);
  1264.  
  1265.     foo = 0;
  1266.     if (needs_refresh & REFRESH_MENU_TEXTURE)
  1267.         foo |= WTextureSettings;
  1268.     if (needs_refresh & REFRESH_MENU_FONT)
  1269.         foo |= WFontSettings;
  1270.     if (needs_refresh & REFRESH_MENU_COLOR)
  1271.         foo |= WColorSettings;
  1272.         if (foo)
  1273.         WMPostNotificationName(WNMenuAppearanceSettingsChanged, NULL,
  1274.                    (void*)foo);
  1275.  
  1276.     foo = 0;
  1277.         if (needs_refresh & REFRESH_WINDOW_FONT) {
  1278.         foo |= WFontSettings;
  1279.     }
  1280.     if (needs_refresh & REFRESH_WINDOW_TEXTURES) {
  1281.         foo |= WTextureSettings;
  1282.     }
  1283.     if (needs_refresh & REFRESH_WINDOW_TITLE_COLOR) {
  1284.         foo |= WColorSettings;
  1285.     }
  1286.     if (foo)
  1287.         WMPostNotificationName(WNWindowAppearanceSettingsChanged, NULL,
  1288.                    (void*)foo);
  1289.  
  1290.     if (!(needs_refresh & REFRESH_ICON_TILE)) {
  1291.         foo = 0;
  1292.         if (needs_refresh & REFRESH_ICON_FONT) {
  1293.         foo |= WFontSettings;
  1294.         }
  1295.         if (needs_refresh & REFRESH_ICON_TITLE_COLOR) {
  1296.         foo |= WTextureSettings;
  1297.         }
  1298.         if (needs_refresh & REFRESH_ICON_TITLE_BACK) {
  1299.         foo |= WTextureSettings;
  1300.         }
  1301.         if (foo)
  1302.         WMPostNotificationName(WNIconAppearanceSettingsChanged, NULL,
  1303.                        (void*)foo);
  1304.     }
  1305.         if (needs_refresh & REFRESH_ICON_TILE)
  1306.         WMPostNotificationName(WNIconTileSettingsChanged, NULL,  NULL);
  1307.     }
  1308. }
  1309.  
  1310.  
  1311. void
  1312. wDefaultUpdateIcons(WScreen *scr)
  1313. {
  1314.     WAppIcon *aicon = scr->app_icon_list;
  1315.     WWindow *wwin = scr->focused_window;
  1316.     char *file;
  1317.  
  1318.     while(aicon) {
  1319.         file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class,
  1320.                    False);
  1321.         if ((file && aicon->icon->file && strcmp(file, aicon->icon->file)!=0)
  1322.             || (file && !aicon->icon->file)) {
  1323.             RImage *new_image;
  1324.  
  1325.             if (aicon->icon->file)
  1326.                 free(aicon->icon->file);
  1327.             aicon->icon->file = wstrdup(file);
  1328.  
  1329.             new_image = wDefaultGetImage(scr, aicon->wm_instance,
  1330.                      aicon->wm_class);
  1331.             if (new_image) {
  1332.                 wIconChangeImage(aicon->icon, new_image);
  1333.                 wAppIconPaint(aicon);
  1334.             }
  1335.         }
  1336.         aicon = aicon->next;
  1337.     }
  1338.  
  1339.     if (!wPreferences.flags.noclip)
  1340.         wClipIconPaint(scr->clip_icon);
  1341.  
  1342.     while (wwin) {
  1343.         if (wwin->icon && wwin->flags.miniaturized) {
  1344.             file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
  1345.                     False);
  1346.             if ((file && wwin->icon->file && strcmp(file, wwin->icon->file)!=0)
  1347.                 || (file && !wwin->icon->file)) {
  1348.                 RImage *new_image;
  1349.  
  1350.                 if (wwin->icon->file)
  1351.                     free(wwin->icon->file);
  1352.                 wwin->icon->file = wstrdup(file);
  1353.  
  1354.                 new_image = wDefaultGetImage(scr, wwin->wm_instance,
  1355.                          wwin->wm_class);
  1356.                 if (new_image)
  1357.                     wIconChangeImage(wwin->icon, new_image);
  1358.             }
  1359.         }
  1360.         wwin = wwin->prev;
  1361.     }
  1362. }
  1363.  
  1364.  
  1365. /* --------------------------- Local ----------------------- */
  1366.  
  1367. #define GET_STRING_OR_DEFAULT(x, var) if (!PLIsString(value)) { \
  1368.     wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
  1369.         entry->key, x); \
  1370.     wwarning(_("using default \"%s\" instead"), entry->default_value); \
  1371.     var = entry->default_value;\
  1372.     } else var = PLGetString(value)\
  1373.  
  1374.     
  1375.  
  1376.  
  1377.  
  1378. static int
  1379. string2index(proplist_t key, proplist_t val, proplist_t def,
  1380.          WOptionEnumeration *values)
  1381. {
  1382.     char *str;
  1383.     WOptionEnumeration *v;
  1384.     char buffer[TOTAL_VALUES_LENGTH];
  1385.  
  1386.     if (PLIsString(val) && (str = PLGetString(val))) {
  1387.     for (v=values; v->string!=NULL; v++) {
  1388.         if (strcasecmp(v->string, str)==0)
  1389.         return v->value;
  1390.     }
  1391.     }
  1392.  
  1393.     buffer[0] = 0;
  1394.     for (v=values; v->string!=NULL; v++) {
  1395.     if (!v->is_alias) {
  1396.         if (buffer[0]!=0)
  1397.         strcat(buffer, ", ");
  1398.         strcat(buffer, v->string);
  1399.     }
  1400.     }
  1401.     wwarning(_("wrong option value for key \"%s\". Should be one of %s"),
  1402.          PLGetString(key), buffer);
  1403.  
  1404.     if (def) {
  1405.     return string2index(key, val, NULL, values);
  1406.     }
  1407.  
  1408.     return -1;
  1409. }
  1410.  
  1411.  
  1412.  
  1413.  
  1414. /*
  1415.  * value - is the value in the defaults DB
  1416.  * addr - is the address to store the data
  1417.  * ret - is the address to store a pointer to a temporary buffer. ret
  1418.  *     must not be freed and is used by the set functions
  1419.  */
  1420. static int 
  1421. getBool(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  1422.     void **ret)
  1423. {
  1424.     static char data;
  1425.     char *val;
  1426.     int second_pass=0;
  1427.  
  1428.     GET_STRING_OR_DEFAULT("Boolean", val);
  1429.  
  1430. again:
  1431.     if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
  1432.     || strcasecmp(val, "YES")==0) {
  1433.  
  1434.     data = 1;
  1435.     } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
  1436.         || strcasecmp(val, "NO")==0) {
  1437.       data = 0;
  1438.     } else {
  1439.     int i;
  1440.     if (sscanf(val, "%i", &i)==1) {
  1441.         if (i!=0)
  1442.         data = 1;
  1443.         else
  1444.         data = 0;
  1445.     } else {
  1446.         wwarning(_("can't convert \"%s\" to boolean for key \"%s\""),
  1447.              val, entry->key);
  1448.         if (second_pass==0) {
  1449.         val = PLGetString(entry->plvalue);
  1450.         second_pass = 1;
  1451.         wwarning(_("using default \"%s\" instead"), val);
  1452.         goto again;
  1453.         }
  1454.         return False;
  1455.     }
  1456.     }
  1457.     
  1458.     if (ret)
  1459.       *ret = &data;
  1460.     
  1461.     if (addr) {
  1462.     *(char*)addr = data;
  1463.     }
  1464.     
  1465.     return True;
  1466. }
  1467.  
  1468.  
  1469. static int 
  1470. getInt(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  1471.        void **ret)
  1472. {
  1473.     static int data;
  1474.     char *val;
  1475.     
  1476.     
  1477.     GET_STRING_OR_DEFAULT("Integer", val);
  1478.     
  1479.     if (sscanf(val, "%i", &data)!=1) {
  1480.         wwarning(_("can't convert \"%s\" to integer for key \"%s\""),
  1481.                  val, entry->key);
  1482.         val = PLGetString(entry->plvalue);
  1483.         wwarning(_("using default \"%s\" instead"), val);
  1484.         if (sscanf(val, "%i", &data)!=1) {
  1485.             return False;
  1486.         }
  1487.     }
  1488.     
  1489.     if (ret)
  1490.       *ret = &data;
  1491.     
  1492.     if (addr) {
  1493.     *(int*)addr = data;
  1494.     }
  1495.     return True;
  1496. }
  1497.  
  1498.  
  1499. static int 
  1500. getCoord(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  1501.          void **ret)
  1502. {
  1503.     static WCoord data;
  1504.     char *val_x, *val_y;
  1505.     int nelem, changed=0;
  1506.     proplist_t elem_x, elem_y;
  1507.  
  1508. again:
  1509.     if (!PLIsArray(value)) {
  1510.         wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  1511.                  entry->key, "Coordinate");
  1512.         if (changed==0) {
  1513.             value = entry->plvalue;
  1514.             changed = 1;
  1515.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1516.             goto again;
  1517.         }
  1518.         return False;
  1519.     }
  1520.  
  1521.     nelem = PLGetNumberOfElements(value);
  1522.     if (nelem != 2) {
  1523.         wwarning(_("Incorrect number of elements in array for key \"%s\"."),
  1524.                  entry->key);
  1525.         if (changed==0) {
  1526.             value = entry->plvalue;
  1527.             changed = 1;
  1528.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1529.             goto again;
  1530.         }
  1531.         return False;
  1532.     }
  1533.  
  1534.     elem_x = PLGetArrayElement(value, 0);
  1535.     elem_y = PLGetArrayElement(value, 1);
  1536.     
  1537.     if (!elem_x || !elem_y || !PLIsString(elem_x) || !PLIsString(elem_y)) {
  1538.         wwarning(_("Wrong value for key \"%s\". Should be Coordinate."),
  1539.                  entry->key);
  1540.         if (changed==0) {
  1541.             value = entry->plvalue;
  1542.             changed = 1;
  1543.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1544.             goto again;
  1545.         }
  1546.         return False;
  1547.     }
  1548.  
  1549.     val_x = PLGetString(elem_x);
  1550.     val_y = PLGetString(elem_y);
  1551.  
  1552.     if (sscanf(val_x, "%i", &data.x)!=1 || sscanf(val_y, "%i", &data.y)!=1) {
  1553.         wwarning(_("can't convert array to integers for \"%s\"."), entry->key);
  1554.         if (changed==0) {
  1555.             value = entry->plvalue;
  1556.             changed = 1;
  1557.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1558.             goto again;
  1559.         }
  1560.         return False;
  1561.     }
  1562.  
  1563.     if (data.x < 0)
  1564.         data.x = 0;
  1565.     else if (data.x > scr->scr_width/3)
  1566.         data.x = scr->scr_width/3;
  1567.     if (data.y < 0)
  1568.         data.y = 0;
  1569.     else if (data.y > scr->scr_height/3)
  1570.         data.y = scr->scr_height/3;
  1571.  
  1572.     if (ret)
  1573.         *ret = &data;
  1574.  
  1575.     if (addr) {
  1576.         *(WCoord*)addr = data;
  1577.     }
  1578.  
  1579.     return True;
  1580. }
  1581.  
  1582.  
  1583. #if 0
  1584. /* This function is not used at the moment. */
  1585. static int 
  1586. getString(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  1587.       void **ret)
  1588. {
  1589.     static char *data;
  1590.     
  1591.     GET_STRING_OR_DEFAULT("String", data);
  1592.     
  1593.     if (!data) {
  1594.         data = PLGetString(entry->plvalue);
  1595.         if (!data)
  1596.             return False;
  1597.     }
  1598.     
  1599.     if (ret)
  1600.       *ret = &data;
  1601.     
  1602.     if (addr)
  1603.       *(char**)addr = wstrdup(data);
  1604.     
  1605.     return True;
  1606. }
  1607. #endif
  1608.  
  1609.  
  1610. static int 
  1611. getPathList(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  1612.         void **ret)
  1613. {
  1614.     static char *data;
  1615.     int i, count, len;
  1616.     char *ptr;
  1617.     proplist_t d;
  1618.     int changed=0;
  1619.  
  1620. again:
  1621.     if (!PLIsArray(value)) {
  1622.     wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  1623.                  entry->key, "an array of paths");
  1624.         if (changed==0) {
  1625.             value = entry->plvalue;
  1626.             changed = 1;
  1627.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1628.             goto again;
  1629.         }
  1630.     return False; 
  1631.     }
  1632.  
  1633.     i = 0;
  1634.     count = PLGetNumberOfElements(value);
  1635.     if (count < 1) {
  1636.         if (changed==0) {
  1637.             value = entry->plvalue;
  1638.             changed = 1;
  1639.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  1640.             goto again;
  1641.         }
  1642.         return False;
  1643.     }
  1644.  
  1645.     len = 0;
  1646.     for (i=0; i<count; i++) {
  1647.     d = PLGetArrayElement(value, i);
  1648.     if (!d || !PLIsString(d)) {
  1649.         count = i;
  1650.         break;
  1651.     }
  1652.     len += strlen(PLGetString(d))+1;
  1653.     }
  1654.  
  1655.     ptr = data = wmalloc(len+1);
  1656.  
  1657.     for (i=0; i<count; i++) {
  1658.     d = PLGetArrayElement(value, i);
  1659.     if (!d || !PLIsString(d)) {
  1660.         break;
  1661.     }
  1662.     strcpy(ptr, PLGetString(d));
  1663.     ptr += strlen(PLGetString(d));
  1664.     *ptr = ':';
  1665.     ptr++;
  1666.     }
  1667.     ptr--; *(ptr--) = 0;
  1668.  
  1669.     if (*(char**)addr!=NULL) {
  1670.     free(*(char**)addr);
  1671.     }
  1672.     *(char**)addr = data;
  1673.  
  1674.     return True;
  1675. }
  1676.  
  1677.  
  1678. static int 
  1679. getEnum(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  1680.     void **ret)
  1681. {
  1682.     static signed char data;
  1683.  
  1684.     data = string2index(entry->plkey, value, entry->default_value,
  1685.             (WOptionEnumeration*)entry->extra_data);
  1686.     if (data < 0)
  1687.     return False;
  1688.  
  1689.     if (ret)
  1690.       *ret = &data;
  1691.  
  1692.     if (addr)
  1693.       *(signed char*)addr = data;
  1694.     
  1695.     return True;    
  1696. }
  1697.  
  1698.  
  1699.  
  1700. /*
  1701.  * (solid <color>)
  1702.  * (hgradient <color> <color>)
  1703.  * (vgradient <color> <color>)
  1704.  * (dgradient <color> <color>)
  1705.  * (mhgradient <color> <color> ...)
  1706.  * (mvgradient <color> <color> ...)
  1707.  * (tpixmap <file> <color>)
  1708.  * (spixmap <file> <color>)
  1709.  * (cpixmap <file> <color>)
  1710.  * (thgradient <file> <opaqueness> <color> <color>)
  1711.  * (tvgradient <file> <opaqueness> <color> <color>)
  1712.  * (tdgradient <file> <opaqueness> <color> <color>)
  1713.  * (function <lib> <function> ...)
  1714.  */
  1715.  
  1716. static WTexture*
  1717. parse_texture(WScreen *scr, proplist_t pl)
  1718. {
  1719.     proplist_t elem;
  1720.     char *val;
  1721.     int nelem;
  1722.     WTexture *texture=NULL;
  1723.     
  1724.     nelem = PLGetNumberOfElements(pl);
  1725.     if (nelem < 1)
  1726.       return NULL;
  1727.     
  1728.     
  1729.     elem = PLGetArrayElement(pl, 0);
  1730.     if (!elem || !PLIsString(elem))
  1731.       return NULL;
  1732.     val = PLGetString(elem);
  1733.  
  1734.     
  1735.     if (strcasecmp(val, "solid")==0) {
  1736.     XColor color;
  1737.  
  1738.     if (nelem != 2)
  1739.         return NULL;
  1740.  
  1741.     /* get color */
  1742.     
  1743.     elem = PLGetArrayElement(pl, 1);
  1744.     if (!elem || !PLIsString(elem)) 
  1745.       return NULL;
  1746.     val = PLGetString(elem);
  1747.  
  1748.     if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
  1749.         wwarning(_("\"%s\" is not a valid color name"), val);
  1750.         return NULL;
  1751.     }
  1752.     
  1753.     texture = (WTexture*)wTextureMakeSolid(scr, &color);
  1754.     } else if (strcasecmp(val, "dgradient")==0
  1755.            || strcasecmp(val, "vgradient")==0
  1756.            || strcasecmp(val, "hgradient")==0) {
  1757.     RColor color1, color2;
  1758.     XColor xcolor;
  1759.     int type;
  1760.  
  1761.     if (nelem != 3) {
  1762.         wwarning(_("bad number of arguments in gradient specification"));
  1763.         return NULL;
  1764.     }
  1765.  
  1766.     if (val[0]=='d' || val[0]=='D')
  1767.       type = WTEX_DGRADIENT;
  1768.     else if (val[0]=='h' || val[0]=='H')
  1769.       type = WTEX_HGRADIENT;
  1770.     else
  1771.       type = WTEX_VGRADIENT;
  1772.  
  1773.     
  1774.     /* get from color */
  1775.     elem = PLGetArrayElement(pl, 1);
  1776.     if (!elem || !PLIsString(elem)) 
  1777.       return NULL;
  1778.     val = PLGetString(elem);
  1779.  
  1780.     if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
  1781.         wwarning(_("\"%s\" is not a valid color name"), val);
  1782.         return NULL;
  1783.     }
  1784.     color1.alpha = 255;
  1785.     color1.red = xcolor.red >> 8;
  1786.     color1.green = xcolor.green >> 8;
  1787.     color1.blue = xcolor.blue >> 8;
  1788.     
  1789.     /* get to color */
  1790.     elem = PLGetArrayElement(pl, 2);
  1791.     if (!elem || !PLIsString(elem)) {
  1792.         return NULL;
  1793.     }
  1794.     val = PLGetString(elem);
  1795.  
  1796.     if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
  1797.         wwarning(_("\"%s\" is not a valid color name"), val);
  1798.         return NULL;
  1799.     }
  1800.     color2.alpha = 255;
  1801.     color2.red = xcolor.red >> 8;
  1802.     color2.green = xcolor.green >> 8;
  1803.     color2.blue = xcolor.blue >> 8;
  1804.  
  1805.     texture = (WTexture*)wTextureMakeGradient(scr, type, &color1, &color2);
  1806.     
  1807.     } else if (strcasecmp(val, "mhgradient")==0
  1808.            || strcasecmp(val, "mvgradient")==0
  1809.            || strcasecmp(val, "mdgradient")==0) {
  1810.     XColor color;
  1811.     RColor **colors;
  1812.     int i, count;
  1813.     int type;
  1814.  
  1815.     if (nelem < 3) {
  1816.         wwarning(_("too few arguments in multicolor gradient specification"));
  1817.         return NULL;
  1818.     }
  1819.  
  1820.     if (val[1]=='h' || val[1]=='H')
  1821.         type = WTEX_MHGRADIENT;
  1822.     else if (val[1]=='v' || val[1]=='V')
  1823.         type = WTEX_MVGRADIENT;
  1824.     else
  1825.         type = WTEX_MDGRADIENT;
  1826.  
  1827.     count = nelem-1;
  1828.  
  1829.     colors = wmalloc(sizeof(RColor*)*(count+1));
  1830.  
  1831.     for (i=0; i<count; i++) {
  1832.         elem = PLGetArrayElement(pl, i+1);
  1833.         if (!elem || !PLIsString(elem)) {
  1834.         for (--i; i>=0; --i) {
  1835.             free(colors[i]);
  1836.         }
  1837.         free(colors);
  1838.         return NULL;
  1839.         }
  1840.         val = PLGetString(elem);
  1841.  
  1842.         if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
  1843.         wwarning(_("\"%s\" is not a valid color name"), val);
  1844.         for (--i; i>=0; --i) {
  1845.             free(colors[i]);
  1846.         }
  1847.         free(colors);
  1848.         return NULL;
  1849.         } else {
  1850.         colors[i] = wmalloc(sizeof(RColor));
  1851.         colors[i]->red = color.red >> 8;
  1852.         colors[i]->green = color.green >> 8;
  1853.         colors[i]->blue = color.blue >> 8;
  1854.         }
  1855.     }
  1856.     colors[i] = NULL;
  1857.     
  1858.     texture = (WTexture*)wTextureMakeMGradient(scr, type, colors);
  1859.     } else if (strcasecmp(val, "spixmap")==0 ||
  1860.            strcasecmp(val, "cpixmap")==0 ||
  1861.                strcasecmp(val, "tpixmap")==0) {
  1862.     XColor color;
  1863.         int type;
  1864.  
  1865.     if (nelem != 3) 
  1866.         return NULL;
  1867.  
  1868.         if (val[0] == 's' || val[0] == 'S')
  1869.             type = WTP_SCALE;
  1870.         else if (val[0] == 'c' || val[0] == 'C')
  1871.         type = WTP_CENTER;
  1872.     else
  1873.             type = WTP_TILE;
  1874.  
  1875.     /* get color */
  1876.     elem = PLGetArrayElement(pl, 2);
  1877.     if (!elem || !PLIsString(elem)) {
  1878.         return NULL;
  1879.     }
  1880.     val = PLGetString(elem);
  1881.  
  1882.     if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
  1883.         wwarning(_("\"%s\" is not a valid color name"), val);
  1884.         return NULL;
  1885.     }
  1886.     
  1887.     /* file name */
  1888.     elem = PLGetArrayElement(pl, 1);
  1889.     if (!elem || !PLIsString(elem)) 
  1890.       return NULL;
  1891.     val = PLGetString(elem);
  1892.  
  1893.     texture = (WTexture*)wTextureMakePixmap(scr, type, val, &color);
  1894.     } else if (strcasecmp(val, "thgradient")==0
  1895.            || strcasecmp(val, "tvgradient")==0
  1896.            || strcasecmp(val, "tdgradient")==0) {
  1897.     RColor color1, color2;
  1898.     XColor xcolor;
  1899.     int opacity;
  1900.     int style;
  1901.  
  1902.     if (val[1]=='h' || val[1]=='H')
  1903.         style = WTEX_THGRADIENT;
  1904.     else if (val[1]=='v' || val[1]=='V')
  1905.         style = WTEX_TVGRADIENT;
  1906.     else
  1907.         style = WTEX_TDGRADIENT;
  1908.  
  1909.     if (nelem != 5) {
  1910.         wwarning(_("bad number of arguments in textured gradient specification"));
  1911.         return NULL;
  1912.     }
  1913.     
  1914.     /* get from color */
  1915.     elem = PLGetArrayElement(pl, 3);
  1916.     if (!elem || !PLIsString(elem)) 
  1917.       return NULL;
  1918.     val = PLGetString(elem);
  1919.  
  1920.     if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
  1921.         wwarning(_("\"%s\" is not a valid color name"), val);
  1922.         return NULL;
  1923.     }
  1924.     color1.alpha = 255;
  1925.     color1.red = xcolor.red >> 8;
  1926.     color1.green = xcolor.green >> 8;
  1927.     color1.blue = xcolor.blue >> 8;
  1928.  
  1929.     /* get to color */
  1930.     elem = PLGetArrayElement(pl, 4);
  1931.     if (!elem || !PLIsString(elem)) {
  1932.         return NULL;
  1933.     }
  1934.     val = PLGetString(elem);
  1935.  
  1936.     if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
  1937.         wwarning(_("\"%s\" is not a valid color name"), val);
  1938.         return NULL;
  1939.     }
  1940.     color2.alpha = 255;
  1941.     color2.red = xcolor.red >> 8;
  1942.     color2.green = xcolor.green >> 8;
  1943.     color2.blue = xcolor.blue >> 8;
  1944.  
  1945.     /* get opacity */
  1946.     elem = PLGetArrayElement(pl, 2);
  1947.     if (!elem || !PLIsString(elem))
  1948.         opacity = 128;
  1949.     else
  1950.         val = PLGetString(elem);
  1951.     
  1952.     if (!val || (opacity = atoi(val)) < 0 || opacity > 255) {
  1953.         wwarning(_("bad opacity value for tgradient texture \"%s\". Should be [0..255]"), val);
  1954.         opacity = 128;
  1955.     }
  1956.  
  1957.     /* get file name */
  1958.     elem = PLGetArrayElement(pl, 1);
  1959.     if (!elem || !PLIsString(elem))
  1960.       return NULL;
  1961.     val = PLGetString(elem);
  1962.  
  1963.     texture = (WTexture*)wTextureMakeTGradient(scr, style, &color1, &color2,
  1964.                            val, opacity);
  1965.     }
  1966. #ifdef TEXTURE_PLUGIN
  1967.     else if (strcasecmp(val, "function")==0) {
  1968.     WTexFunction *function;
  1969.     void (*initFunc) (Display *, Colormap);
  1970.     char *lib, *func, **argv;
  1971.     int i, argc;
  1972.  
  1973.         if (nelem < 3)
  1974.         return NULL;
  1975.  
  1976.     /* get the library name */
  1977.     elem = PLGetArrayElement(pl, 1);
  1978.     if (!elem || !PLIsString(elem)) {
  1979.         return NULL;
  1980.     }
  1981.     lib = PLGetString(elem);
  1982.  
  1983.     /* get the function name */
  1984.     elem = PLGetArrayElement(pl, 2);
  1985.     if (!elem || !PLIsString(elem)) {
  1986.         return NULL;
  1987.     }
  1988.     func = PLGetString(elem);
  1989.  
  1990.     argc = nelem - 2;
  1991.     argv = (char **)wmalloc(argc * sizeof(char *));
  1992.  
  1993.     /* get the parameters */
  1994.     argv[0] = wstrdup(func);
  1995.     for (i = 0; i < argc - 1; i++) {
  1996.         elem = PLGetArrayElement(pl, 3 + i);
  1997.         if (!elem || !PLIsString(elem)) {
  1998.         free(argv);
  1999.  
  2000.         return NULL;
  2001.         }
  2002.         argv[i+1] = wstrdup(PLGetString(elem));
  2003.     }
  2004.  
  2005.     function = wTextureMakeFunction(scr, lib, func, argc, argv);
  2006.  
  2007. #ifdef HAVE_DLFCN_H
  2008.     if (function) {
  2009.         initFunc = dlsym(function->handle, "initWindowMaker");
  2010.         if (initFunc) {
  2011.         initFunc(dpy, scr->w_colormap);
  2012.         } else {
  2013.         wwarning(_("could not initialize library %s"), lib);
  2014.         }
  2015.     } else {
  2016.         wwarning(_("could not find function %s::%s"), lib, func);
  2017.     }
  2018. #endif /* HAVE_DLFCN_H */
  2019.     texture = (WTexture*)function;
  2020.     }
  2021. #endif /* TEXTURE_PLUGIN */
  2022.     else {
  2023.     wwarning(_("invalid texture type %s"), val);
  2024.     return NULL;
  2025.     }
  2026.     return texture;
  2027. }
  2028.  
  2029.  
  2030.  
  2031. static int 
  2032. getTexture(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  2033.        void **ret)
  2034. {
  2035.     static WTexture *texture;
  2036.     int changed=0;
  2037.  
  2038. again:
  2039.     if (!PLIsArray(value)) { 
  2040.     wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  2041.          entry->key, "Texture");
  2042.         if (changed==0) {
  2043.             value = entry->plvalue;
  2044.             changed = 1;
  2045.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  2046.             goto again;
  2047.         }
  2048.         return False;
  2049.     }
  2050.     
  2051.     if (strcmp(entry->key, "WidgetColor")==0 && !changed) {
  2052.     proplist_t pl;
  2053.     
  2054.     pl = PLGetArrayElement(value, 0);
  2055.     if (!pl || !PLIsString(pl) || !PLGetString(pl)
  2056.         || strcasecmp(PLGetString(pl), "solid")!=0) {
  2057.         wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  2058.              entry->key, "Solid Texture");
  2059.  
  2060.         value = entry->plvalue;
  2061.         changed = 1;
  2062.         wwarning(_("using default \"%s\" instead"), entry->default_value);
  2063.         goto again;
  2064.     }
  2065.     }
  2066.  
  2067.     texture = parse_texture(scr, value);
  2068.  
  2069.     if (!texture) {
  2070.     wwarning(_("Error in texture specification for key \"%s\""),
  2071.          entry->key);
  2072.         if (changed==0) {
  2073.             value = entry->plvalue;
  2074.             changed = 1;
  2075.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  2076.             goto again;
  2077.         }
  2078.         return False;
  2079.     }
  2080.     
  2081.     if (ret) 
  2082.       *ret = &texture;
  2083.  
  2084.     if (addr)
  2085.       *(WTexture**)addr = texture;
  2086.     
  2087.     return True;
  2088. }
  2089.  
  2090.  
  2091.  
  2092. #ifdef DRAWSTRING_PLUGIN
  2093. static int
  2094. getTextRenderer(WScreen *scr, WDefaultEntry *entry, proplist_t value,
  2095.         void *addr, void **ret)
  2096. {
  2097.     proplist_t elem;
  2098.     char *val, *lib, *func, **argv;
  2099.     int argc, changed;
  2100.  
  2101.     if (strcmp(entry->key, "FTitleColor")==0) {
  2102.         wPluginDestroyFunction(scr->drawstring_func[changed = W_STRING_FTITLE]);
  2103.         scr->drawstring_func[W_STRING_FTITLE] = NULL;
  2104.     } else if (strcmp(entry->key, "UTitleColor")==0) {
  2105.         wPluginDestroyFunction(scr->drawstring_func[changed = W_STRING_UTITLE]);
  2106.         scr->drawstring_func[W_STRING_UTITLE] = NULL;
  2107.     } else if (strcmp(entry->key, "PTitleColor")==0) {
  2108.         wPluginDestroyFunction(scr->drawstring_func[changed = W_STRING_PTITLE]);
  2109.         scr->drawstring_func[W_STRING_PTITLE] = NULL;
  2110.     } else if (strcmp(entry->key, "MenuTitleColor")==0) {
  2111.         wPluginDestroyFunction(scr->drawstring_func[changed = W_STRING_MTITLE]);
  2112.         scr->drawstring_func[W_STRING_MTITLE] = NULL;
  2113.     } else if (strcmp(entry->key, "MenuPluginColor")==0) {
  2114.         wPluginDestroyFunction(scr->drawstring_func[changed = W_STRING_MTEXT]);
  2115.         scr->drawstring_func[W_STRING_MTEXT] = NULL;
  2116.     }
  2117.  
  2118.     if (PLIsArray(value)) {
  2119.         if ((argc = PLGetNumberOfElements(value)) < 4) return False;
  2120.         argc -= 2;
  2121.         argv = (char **)wmalloc(argc * sizeof(char *));
  2122.  
  2123.         elem = PLGetArrayElement(value,0);
  2124.         if (!elem || !PLIsString(elem)) return False;
  2125.         val = PLGetString(elem);
  2126.         if (strcasecmp(val, "function")==0) {
  2127.             elem = PLGetArrayElement(value, 1); /* library name */
  2128.             if (!elem || !PLIsString(elem)) return False;
  2129.             lib = PLGetString(elem);
  2130.             elem = PLGetArrayElement(value, 2); /* function name */
  2131.             if (!elem || !PLIsString(elem)) return False;
  2132.             func = PLGetString(elem);
  2133.             scr->drawstring_func[changed] = wPluginCreateFunction (W_FUNCTION_DRAWSTRING,
  2134.                     lib, "initDrawString", func, NULL, value,
  2135.                     wPluginPackInitData(3, dpy, scr->w_colormap,"-DATA-"));
  2136.         }
  2137.  
  2138.         return getColor(scr, entry, PLGetArrayElement(value,3), addr, ret);
  2139.     } else if (PLIsString(value)) {
  2140.         return getColor(scr, entry, value, addr, ret);
  2141.     }
  2142.     
  2143.     return False;
  2144. }
  2145. #endif /* DRAWSTRING_PLUGIN */
  2146.  
  2147.  
  2148.  
  2149. static int
  2150. getWSBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
  2151.         void *addr, void **ret)
  2152. {
  2153.     proplist_t elem;
  2154.     int changed = 0;
  2155.     char *val;
  2156.     int nelem;
  2157.  
  2158. again:
  2159.     if (!PLIsArray(value)) {
  2160.     wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  2161.                  "WorkspaceBack", "Texture or None");
  2162.         if (changed==0) {
  2163.             value = entry->plvalue;
  2164.             changed = 1;
  2165.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  2166.             goto again;
  2167.         }
  2168.         return False;
  2169.     }
  2170.  
  2171.     /* only do basic error checking and verify for None texture */
  2172.  
  2173.     nelem = PLGetNumberOfElements(value);
  2174.     if (nelem > 0) {
  2175.     elem = PLGetArrayElement(value, 0);
  2176.     if (!elem || !PLIsString(elem)) {
  2177.         wwarning(_("Wrong type for workspace background. Should be a texture type."));
  2178.         if (changed==0) {
  2179.         value = entry->plvalue;
  2180.         changed = 1;
  2181.         wwarning(_("using default \"%s\" instead"), entry->default_value);
  2182.         goto again;
  2183.         }
  2184.         return False;
  2185.     }
  2186.     val = PLGetString(elem);
  2187.  
  2188.     if (strcasecmp(val, "None")==0)
  2189.         return True;
  2190.     }
  2191.     *ret = PLRetain(value);
  2192.  
  2193.     return True;
  2194. }
  2195.  
  2196.  
  2197. static int
  2198. getWSSpecificBackground(WScreen *scr, WDefaultEntry *entry, proplist_t value,
  2199.             void *addr, void **ret)
  2200. {
  2201.     proplist_t elem;
  2202.     int nelem;
  2203.     int changed = 0;
  2204.  
  2205. again:
  2206.     if (!PLIsArray(value)) {
  2207.     wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  2208.                  "WorkspaceSpecificBack", "an array of textures");
  2209.         if (changed==0) {
  2210.             value = entry->plvalue;
  2211.             changed = 1;
  2212.             wwarning(_("using default \"%s\" instead"), entry->default_value);
  2213.             goto again;
  2214.         }
  2215.         return False;
  2216.     }
  2217.  
  2218.     /* only do basic error checking and verify for None texture */
  2219.  
  2220.     nelem = PLGetNumberOfElements(value);
  2221.     if (nelem > 0) {
  2222.     while (nelem--) {
  2223.         elem = PLGetArrayElement(value, nelem);
  2224.         if (!elem || !PLIsArray(elem)) {
  2225.         wwarning(_("Wrong type for background of workspace %i. Should be a texture."),
  2226.              nelem);
  2227.         }
  2228.     }
  2229.     }
  2230.  
  2231.     *ret = PLRetain(value);
  2232.  
  2233. #ifdef notworking
  2234.     /* 
  2235.      * Kluge to force wmsetbg helper to set the default background.
  2236.      * If the WorkspaceSpecificBack is changed once wmaker has started,
  2237.      * the WorkspaceBack won't be sent to the helper, unless the user
  2238.      * changes it's value too. So, we must force this by removing the
  2239.      * value from the defaults DB.
  2240.      */
  2241.     if (!scr->flags.backimage_helper_launched && !scr->flags.startup) {
  2242.     proplist_t key = PLMakeString("WorkspaceBack");
  2243.  
  2244.     PLRemoveDictionaryEntry(WDWindowMaker->dictionary, key);
  2245.  
  2246.     PLRelease(key);
  2247.     }
  2248. #endif
  2249.     return True;
  2250. }
  2251.  
  2252.  
  2253. static int 
  2254. getFont(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  2255.     void **ret)
  2256. {
  2257.     static WMFont *font;
  2258.     char *val;
  2259.  
  2260.     GET_STRING_OR_DEFAULT("Font", val);
  2261.  
  2262.     font = WMCreateFont(scr->wmscreen, val);
  2263.     if (!font)
  2264.     font = WMCreateFont(scr->wmscreen, "fixed");
  2265.  
  2266.     if (!font) {
  2267.     wfatal(_("could not load any usable font!!!"));
  2268.     exit(1);
  2269.     }
  2270.  
  2271.     if (ret)
  2272.       *ret = font;
  2273.  
  2274.     /* can't assign font value outside update function */
  2275.     wassertrv(addr == NULL, True);
  2276.     
  2277.     return True;
  2278. }
  2279.  
  2280.  
  2281. static int 
  2282. getColor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  2283.      void **ret)
  2284. {
  2285.     static XColor color;
  2286.     char *val;
  2287.     int second_pass=0;
  2288.  
  2289.     GET_STRING_OR_DEFAULT("Color", val);
  2290.     
  2291.  
  2292. again:
  2293.     if (!wGetColor(scr, val, &color)) {
  2294.         wwarning(_("could not get color for key \"%s\""),
  2295.                  entry->key);
  2296.         if (second_pass==0) {
  2297.             val = PLGetString(entry->plvalue);
  2298.             second_pass = 1;
  2299.             wwarning(_("using default \"%s\" instead"), val);
  2300.             goto again;
  2301.         }
  2302.         return False;
  2303.     }
  2304.  
  2305.     if (ret)
  2306.       *ret = &color;
  2307.     
  2308.     assert(addr==NULL);
  2309.     /*
  2310.     if (addr)
  2311.       *(unsigned long*)addr = pixel;
  2312.      */
  2313.     
  2314.     return True;
  2315. }
  2316.  
  2317.  
  2318.  
  2319. static int
  2320. getKeybind(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  2321.      void **ret)
  2322. {
  2323.     static WShortKey shortcut;
  2324.     KeySym ksym;
  2325.     char *val;
  2326.     char *k;
  2327.     char buf[128], *b;
  2328.  
  2329.  
  2330.     GET_STRING_OR_DEFAULT("Key spec", val);
  2331.  
  2332.     if (!val || strcasecmp(val, "NONE")==0) {
  2333.     shortcut.keycode = 0;
  2334.     shortcut.modifier = 0;
  2335.     if (ret)
  2336.         *ret = &shortcut;
  2337.     return True;
  2338.     }
  2339.  
  2340.     strcpy(buf, val);
  2341.     
  2342.     b = (char*)buf;
  2343.  
  2344.     /* get modifiers */
  2345.     shortcut.modifier = 0;
  2346.     while ((k = strchr(b, '+'))!=NULL) {
  2347.     int mod;
  2348.     
  2349.     *k = 0;
  2350.     mod = wXModifierFromKey(b);
  2351.     if (mod<0) {
  2352.         wwarning(_("%s:invalid key modifier \"%s\""), entry->key, b);
  2353.         return False;
  2354.     }
  2355.     shortcut.modifier |= mod;
  2356.     
  2357.     b = k+1;
  2358.     }
  2359.     
  2360.     /* get key */
  2361.     ksym = XStringToKeysym(b);
  2362.     
  2363.     if (ksym==NoSymbol) {
  2364.     wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key,
  2365.          val);
  2366.     return False;
  2367.     }
  2368.     
  2369.     shortcut.keycode = XKeysymToKeycode(dpy, ksym);
  2370.     if (shortcut.keycode==0) {
  2371.     wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
  2372.     return False;
  2373.     }
  2374.  
  2375.     if (ret)
  2376.       *ret = &shortcut;
  2377.  
  2378.     return True;
  2379. }
  2380.  
  2381.  
  2382. static int
  2383. getModMask(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr, 
  2384.        void **ret)
  2385. {
  2386.     static unsigned int mask;
  2387.     char *str;
  2388.  
  2389.     GET_STRING_OR_DEFAULT("Modifier Key", str);
  2390.  
  2391.     if (!str)
  2392.     return False;
  2393.  
  2394.     mask = wXModifierFromKey(str);
  2395.     if (mask < 0) {
  2396.     wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
  2397.     mask = 0;
  2398.     return False;
  2399.     }
  2400.  
  2401.     if (addr)
  2402.     *(unsigned int*)addr = mask;
  2403.  
  2404.     if (ret)
  2405.     *ret = &mask;
  2406.  
  2407.     return True;
  2408. }
  2409.  
  2410.  
  2411. #ifdef NEWSTUFF
  2412. static int
  2413. getRImages(WScreen *scr, WDefaultEntry *entry, proplist_t value,
  2414.        void *addr, void **ret)
  2415. {
  2416.     unsigned int mask;
  2417.     char *str;
  2418.     RImage *image;
  2419.     int i, n;
  2420.     int w, h;
  2421.  
  2422.     GET_STRING_OR_DEFAULT("Image File Path", str);
  2423.     if (!str)
  2424.     return False;
  2425.  
  2426.     image = RLoadImage(scr->rcontext, str, 0);
  2427.     if (!image) {
  2428.     wwarning(_("could not load image in option %s: %s"), entry->key,
  2429.          RMessageForError(RErrorCode));
  2430.     return False;
  2431.     }
  2432.  
  2433.     if (*(RImage**)addr) {
  2434.     RDestroyImage(*(RImage**)addr);
  2435.     }
  2436.     if (addr)
  2437.     *(RImage**)addr = image;
  2438.  
  2439.     assert(ret == NULL);
  2440.     /*
  2441.     if (ret)
  2442.     *(RImage**)ret = image;
  2443.      */
  2444.  
  2445.     return True;
  2446. }
  2447. #endif
  2448.  
  2449. #ifdef DEFINABLE_CURSOR
  2450.  
  2451. # include <X11/cursorfont.h>
  2452. typedef struct 
  2453. {
  2454.    char *name;
  2455.    int id;
  2456. } WCursorLookup;
  2457.  
  2458. #define CURSOR_ID_NONE    (XC_num_glyphs)
  2459.  
  2460. static WCursorLookup cursor_table[] =
  2461. {
  2462.     { "X_cursor",        XC_X_cursor },
  2463.     { "arrow",            XC_arrow },
  2464.     { "based_arrow_down",    XC_based_arrow_down },
  2465.     { "based_arrow_up",        XC_based_arrow_up },
  2466.     { "boat",            XC_boat },
  2467.     { "bogosity",        XC_bogosity },
  2468.     { "bottom_left_corner",    XC_bottom_left_corner },
  2469.     { "bottom_right_corner",    XC_bottom_right_corner },
  2470.     { "bottom_side",        XC_bottom_side },
  2471.     { "bottom_tee",        XC_bottom_tee },
  2472.     { "box_spiral",        XC_box_spiral },
  2473.     { "center_ptr",        XC_center_ptr },
  2474.     { "circle",            XC_circle },
  2475.     { "clock",            XC_clock },
  2476.     { "coffee_mug",        XC_coffee_mug },
  2477.     { "cross",            XC_cross },
  2478.     { "cross_reverse",        XC_cross_reverse },
  2479.     { "crosshair",        XC_crosshair },
  2480.     { "diamond_cross",        XC_diamond_cross },
  2481.     { "dot",            XC_dot },
  2482.     { "dotbox",            XC_dotbox },
  2483.     { "double_arrow",        XC_double_arrow },
  2484.     { "draft_large",        XC_draft_large },
  2485.     { "draft_small",        XC_draft_small },
  2486.     { "draped_box",        XC_draped_box },
  2487.     { "exchange",        XC_exchange },
  2488.     { "fleur",            XC_fleur },
  2489.     { "gobbler",        XC_gobbler },
  2490.     { "gumby",            XC_gumby },
  2491.     { "hand1",            XC_hand1 },
  2492.     { "hand2",            XC_hand2 },
  2493.     { "heart",            XC_heart },
  2494.     { "icon",            XC_icon },
  2495.     { "iron_cross",        XC_iron_cross },
  2496.     { "left_ptr",        XC_left_ptr },
  2497.     { "left_side",        XC_left_side },
  2498.     { "left_tee",        XC_left_tee },
  2499.     { "leftbutton",        XC_leftbutton },
  2500.     { "ll_angle",        XC_ll_angle },
  2501.     { "lr_angle",        XC_lr_angle },
  2502.     { "man",            XC_man },
  2503.     { "middlebutton",        XC_middlebutton },
  2504.     { "mouse",            XC_mouse },
  2505.     { "pencil",            XC_pencil },
  2506.     { "pirate",            XC_pirate },
  2507.     { "plus",            XC_plus },
  2508.     { "question_arrow",        XC_question_arrow },
  2509.     { "right_ptr",        XC_right_ptr },
  2510.     { "right_side",        XC_right_side },
  2511.     { "right_tee",        XC_right_tee },
  2512.     { "rightbutton",        XC_rightbutton },
  2513.     { "rtl_logo",        XC_rtl_logo },
  2514.     { "sailboat",        XC_sailboat },
  2515.     { "sb_down_arrow",        XC_sb_down_arrow },
  2516.     { "sb_h_double_arrow",    XC_sb_h_double_arrow },
  2517.     { "sb_left_arrow",        XC_sb_left_arrow },
  2518.     { "sb_right_arrow",        XC_sb_right_arrow },
  2519.     { "sb_up_arrow",        XC_sb_up_arrow },
  2520.     { "sb_v_double_arrow",    XC_sb_v_double_arrow },
  2521.     { "shuttle",        XC_shuttle },
  2522.     { "sizing",            XC_sizing },
  2523.     { "spider",            XC_spider },
  2524.     { "spraycan",        XC_spraycan },
  2525.     { "star",            XC_star },
  2526.     { "target",            XC_target },
  2527.     { "tcross",            XC_tcross },
  2528.     { "top_left_arrow",        XC_top_left_arrow },
  2529.     { "top_left_corner",    XC_top_left_corner },
  2530.     { "top_right_corner",    XC_top_right_corner },
  2531.     { "top_side",        XC_top_side },
  2532.     { "top_tee",        XC_top_tee },
  2533.     { "trek",            XC_trek },
  2534.     { "ul_angle",        XC_ul_angle },
  2535.     { "umbrella",        XC_umbrella },
  2536.     { "ur_angle",        XC_ur_angle },
  2537.     { "watch",            XC_watch },
  2538.     { "xterm",            XC_xterm },
  2539.     { NULL,            CURSOR_ID_NONE }
  2540. };
  2541.  
  2542. static void check_bitmap_status(int status, char *filename, Pixmap bitmap)
  2543. {
  2544.    switch(status)
  2545.     {
  2546.      case BitmapOpenFailed:
  2547.        wwarning(_("failed to open bitmap file \"%s\""), filename);
  2548.        break;
  2549.      case BitmapFileInvalid:
  2550.        wwarning(_("\"%s\" is not a valid bitmap file"), filename);
  2551.        break;
  2552.      case BitmapNoMemory:
  2553.        wwarning(_("out of memory reading bitmap file \"%s\""), filename);
  2554.        break;
  2555.      case BitmapSuccess:
  2556.        XFreePixmap(dpy, bitmap);
  2557.        break;
  2558.     }
  2559. }
  2560.  
  2561. /*
  2562.  * (none)
  2563.  * (builtin, <cursor_name>)
  2564.  * (bitmap, <cursor_bitmap>, <cursor_mask>)
  2565.  */
  2566. static int parse_cursor(WScreen *scr, proplist_t pl, Cursor *cursor)
  2567. {
  2568.    proplist_t elem;
  2569.    char *val;
  2570.    int nelem;
  2571.    int status = 0;
  2572.    
  2573.    nelem = PLGetNumberOfElements(pl);
  2574.    if (nelem < 1)
  2575.     {
  2576.        return(status);
  2577.     }
  2578.    elem = PLGetArrayElement(pl, 0);
  2579.    if (!elem || !PLIsString(elem))
  2580.     {
  2581.        return(status);
  2582.     }
  2583.    val = PLGetString(elem);
  2584.    
  2585.    if (0 == strcasecmp(val, "none")) 
  2586.     {
  2587.        status = 1;
  2588.        *cursor = None;
  2589.     }
  2590.    else if (0 == strcasecmp(val, "builtin")) 
  2591.     {
  2592.        int i;
  2593.        int cursor_id = CURSOR_ID_NONE;
  2594.        
  2595.        if (2 != nelem)
  2596.     {
  2597.        wwarning(_("bad number of arguments in cursor specification"));
  2598.        return(status);
  2599.     }
  2600.        elem = PLGetArrayElement(pl, 1);
  2601.        if (!elem || !PLIsString(elem))
  2602.     {
  2603.        return(status);
  2604.     }
  2605.        val = PLGetString(elem);
  2606.        
  2607.        for (i = 0; NULL != cursor_table[i].name; i++)
  2608.     {
  2609.        if (0 == strcasecmp(val, cursor_table[i].name))
  2610.         {
  2611.            cursor_id = cursor_table[i].id;
  2612.            break;
  2613.         }
  2614.     }
  2615.        if (CURSOR_ID_NONE == cursor_id) 
  2616.     {
  2617.        wwarning(_("unknown builtin cursor name \"%s\""), val);
  2618.     }
  2619.        else
  2620.     {
  2621.        *cursor = XCreateFontCursor(dpy, cursor_id);
  2622.        status = 1;
  2623.     }
  2624.     }
  2625.    else if (0 == strcasecmp(val, "bitmap"))
  2626.     {
  2627.        char *bitmap_name;
  2628.        char *mask_name;
  2629.        int bitmap_status;
  2630.        int mask_status;
  2631.        Pixmap bitmap;
  2632.        Pixmap mask;
  2633.        unsigned int w, h;
  2634.        int x, y;
  2635.        XColor fg, bg;
  2636.        
  2637.        if (3 != nelem)
  2638.     {
  2639.        wwarning(_("bad number of arguments in cursor specification"));
  2640.        return(status);
  2641.     }
  2642.        elem = PLGetArrayElement(pl, 1);
  2643.        if (!elem || !PLIsString(elem))
  2644.     {
  2645.        return(status);
  2646.     }
  2647.        val = PLGetString(elem);
  2648.        bitmap_name = FindImage(wPreferences.pixmap_path, val);
  2649.        if (!bitmap_name)
  2650.     {
  2651.        wwarning(_("could not find cursor bitmap file \"%s\""), val);
  2652.        return(status);
  2653.     }
  2654.        elem = PLGetArrayElement(pl, 2);
  2655.        if (!elem || !PLIsString(elem))
  2656.     {
  2657.        free(bitmap_name);
  2658.        return(status);
  2659.     }
  2660.        val = PLGetString(elem);
  2661.        mask_name = FindImage(wPreferences.pixmap_path, val);
  2662.        if (!mask_name)
  2663.     {
  2664.        free(bitmap_name);
  2665.        wwarning(_("could not find cursor bitmap file \"%s\""), val);
  2666.        return(status);
  2667.     }
  2668.        mask_status = XReadBitmapFile(dpy, scr->w_win, mask_name, &w, &h,
  2669.                      &mask, &x, &y);
  2670.        bitmap_status = XReadBitmapFile(dpy, scr->w_win, bitmap_name, &w, &h,
  2671.                        &bitmap, &x, &y);
  2672.        if ((BitmapSuccess == bitmap_status) &&
  2673.        (BitmapSuccess == mask_status))
  2674.     {
  2675.        fg.pixel = scr->black_pixel;
  2676.        bg.pixel = scr->white_pixel;
  2677.        XQueryColor(dpy, scr->w_colormap, &fg);
  2678.        XQueryColor(dpy, scr->w_colormap, &bg);
  2679.        *cursor = XCreatePixmapCursor(dpy, bitmap, mask, &fg, &bg, x, y);
  2680.        status = 1;
  2681.     }
  2682.        check_bitmap_status(bitmap_status, bitmap_name, bitmap);
  2683.        check_bitmap_status(mask_status, mask_name, mask);
  2684.        free(bitmap_name);
  2685.        free(mask_name);
  2686.     }
  2687.    return(status);
  2688. }
  2689.  
  2690. static int
  2691. getCursor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
  2692.       void **ret)
  2693. {
  2694.    static Cursor cursor;
  2695.    int status;
  2696.    int changed = 0;
  2697.    
  2698. again:
  2699.    if (!PLIsArray(value))
  2700.     {
  2701.        wwarning(_("Wrong option format for key \"%s\". Should be %s."),
  2702.         entry->key, "cursor specification");
  2703.        if (!changed)
  2704.     {
  2705.        value = entry->plvalue;
  2706.        changed = 1;
  2707.        wwarning(_("using default \"%s\" instead"), entry->default_value);
  2708.        goto again;
  2709.     }
  2710.        return(False);
  2711.     }
  2712.    status = parse_cursor(scr, value, &cursor);
  2713.    if (!status)
  2714.     {
  2715.        wwarning(_("Error in cursor specification for key \"%s\""), entry->key);
  2716.        if (!changed)
  2717.     {
  2718.        value = entry->plvalue;
  2719.        changed = 1;
  2720.        wwarning(_("using default \"%s\" instead"), entry->default_value);
  2721.        goto again;
  2722.     }
  2723.        return(False);
  2724.     }
  2725.    if (ret)
  2726.     {
  2727.        *ret = &cursor;
  2728.     }
  2729.    if (addr)
  2730.     {
  2731.        *(Cursor *)addr = cursor;
  2732.     }
  2733.    return(True);
  2734. }
  2735. #undef CURSOR_ID_NONE
  2736.  
  2737. #endif /* DEFINABLE_CURSOR */
  2738.  
  2739.  
  2740. /* ---------------- value setting functions --------------- */
  2741. static int
  2742. setJustify(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  2743. {
  2744.     return REFRESH_WINDOW_TITLE_COLOR;
  2745. }
  2746.  
  2747. static int
  2748. setClearance(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
  2749. {
  2750.     return REFRESH_WINDOW_FONT|REFRESH_BUTTON_IMAGES|REFRESH_MENU_TITLE_FONT|REFRESH_MENU_FONT;
  2751. }
  2752.  
  2753. static int
  2754. setIfDockPresent(WScreen *scr, WDefaultEntry *entry, char *flag, long which)
  2755. {
  2756.     switch (which) {
  2757.     case WM_DOCK:
  2758.         wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
  2759.         break;
  2760.     case WM_CLIP:
  2761.         wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
  2762.         break;
  2763.     default:
  2764.         break;
  2765.     }
  2766.     return 0;
  2767. }
  2768.  
  2769.  
  2770. static int
  2771. setStickyIcons(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
  2772. {
  2773.     if (scr->workspaces) {
  2774.         wWorkspaceForceChange(scr, scr->current_workspace);
  2775.         wArrangeIcons(scr, False);
  2776.     }
  2777.     return 0;
  2778. }
  2779.  
  2780. #if not_used
  2781. static int
  2782. setPositive(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
  2783. {
  2784.     if (*value <= 0)
  2785.         *(int*)foo = 1;
  2786.  
  2787.     return 0;
  2788. }
  2789. #endif
  2790.  
  2791.  
  2792.  
  2793. static int
  2794. setIconTile(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  2795. {
  2796.     Pixmap pixmap;
  2797.     RImage *img;
  2798.     int reset = 0;
  2799.    
  2800.     img = wTextureRenderImage(*texture, wPreferences.icon_size,
  2801.                   wPreferences.icon_size,
  2802.                   ((*texture)->any.type & WREL_BORDER_MASK)
  2803.                   ? WREL_ICON : WREL_FLAT);
  2804.     if (!img) {
  2805.     wwarning(_("could not render texture for icon background"));
  2806.     if (!entry->addr)
  2807.       wTextureDestroy(scr, *texture);
  2808.     return 0;
  2809.     }
  2810.     RConvertImage(scr->rcontext, img, &pixmap);
  2811.     
  2812.     if (scr->icon_tile) {
  2813.     reset = 1;
  2814.     RDestroyImage(scr->icon_tile);
  2815.     XFreePixmap(dpy, scr->icon_tile_pixmap);
  2816.     }
  2817.  
  2818.     scr->icon_tile = img;
  2819.     
  2820.     
  2821.     /* put the icon in the noticeboard hint */
  2822.     PropSetIconTileHint(scr, img);
  2823.     
  2824.  
  2825.     if (!wPreferences.flags.noclip) {
  2826.     if (scr->clip_tile) {
  2827.         RDestroyImage(scr->clip_tile);
  2828.     }
  2829.     scr->clip_tile = wClipMakeTile(scr, img);
  2830.     }
  2831.  
  2832.     scr->icon_tile_pixmap = pixmap;
  2833.  
  2834.     if (scr->def_icon_pixmap) {
  2835.         XFreePixmap(dpy, scr->def_icon_pixmap);
  2836.         scr->def_icon_pixmap = None;
  2837.     }
  2838.     if (scr->def_ticon_pixmap) {
  2839.         XFreePixmap(dpy, scr->def_ticon_pixmap);
  2840.         scr->def_ticon_pixmap = None;
  2841.     }
  2842.  
  2843.     if (scr->icon_back_texture) {
  2844.     wTextureDestroy(scr, (WTexture*)scr->icon_back_texture);
  2845.     }
  2846.     scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
  2847.  
  2848.     if (scr->clip_balloon)
  2849.     XSetWindowBackground(dpy, scr->clip_balloon, 
  2850.                  (*texture)->any.color.pixel);
  2851.     
  2852.     /*
  2853.      * Free the texture as nobody else will use it, nor refer to it.
  2854.      */
  2855.     if (!entry->addr)
  2856.     wTextureDestroy(scr, *texture);
  2857.  
  2858.     return (reset ? REFRESH_ICON_TILE : 0);
  2859. }
  2860.  
  2861.  
  2862.  
  2863. static int 
  2864. setWinTitleFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2865. {
  2866.     if (scr->title_font) {
  2867.     WMReleaseFont(scr->title_font);
  2868.     }
  2869.     scr->title_font = font;
  2870.     
  2871.     return REFRESH_WINDOW_FONT|REFRESH_BUTTON_IMAGES;
  2872. }
  2873.  
  2874.  
  2875. static int 
  2876. setMenuTitleFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2877. {
  2878.     if (scr->menu_title_font) {
  2879.     WMReleaseFont(scr->menu_title_font);
  2880.     }
  2881.     
  2882.     scr->menu_title_font = font;
  2883.  
  2884.     return REFRESH_MENU_TITLE_FONT;
  2885. }
  2886.  
  2887.  
  2888. static int 
  2889. setMenuTextFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2890. {
  2891.     if (scr->menu_entry_font) {
  2892.     WMReleaseFont(scr->menu_entry_font);
  2893.     }    
  2894.     scr->menu_entry_font = font;
  2895.  
  2896.     return REFRESH_MENU_FONT;
  2897. }
  2898.  
  2899.  
  2900.  
  2901. static int 
  2902. setIconTitleFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2903. {
  2904.     if (scr->icon_title_font) {
  2905.     WMReleaseFont(scr->icon_title_font);
  2906.     }
  2907.     
  2908.     scr->icon_title_font = font;
  2909.          
  2910.     return REFRESH_ICON_FONT;
  2911. }
  2912.  
  2913.  
  2914. static int 
  2915. setClipTitleFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2916. {
  2917.     if (scr->clip_title_font) {
  2918.     WMReleaseFont(scr->clip_title_font);
  2919.     }
  2920.     
  2921.     scr->clip_title_font = font;
  2922.  
  2923.     return REFRESH_ICON_FONT;
  2924. }
  2925.  
  2926.  
  2927. static int
  2928. setLargeDisplayFont(WScreen *scr, WDefaultEntry *entry, WMFont *font, void *foo)
  2929. {
  2930.     if (scr->workspace_name_font) {
  2931.     WMReleaseFont(scr->workspace_name_font);
  2932.     }
  2933.     
  2934.     scr->workspace_name_font = font;
  2935.  
  2936.     return 0;
  2937. }
  2938.  
  2939.  
  2940. static int
  2941. setHightlight(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  2942. {
  2943.    if (scr->select_pixel!=scr->white_pixel &&
  2944.     scr->select_pixel!=scr->black_pixel) {
  2945.     wFreeColor(scr, scr->select_pixel);
  2946.     }
  2947.     
  2948.     scr->select_pixel = color->pixel;
  2949.  
  2950.     return REFRESH_MENU_COLOR;
  2951. }
  2952.  
  2953.  
  2954. static int
  2955. setHightlightText(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  2956. {
  2957.    if (scr->select_text_pixel!=scr->white_pixel &&
  2958.     scr->select_text_pixel!=scr->black_pixel) {
  2959.     wFreeColor(scr, scr->select_text_pixel);
  2960.     }
  2961.     
  2962.     scr->select_text_pixel = color->pixel;
  2963.  
  2964.     return REFRESH_MENU_COLOR;
  2965. }
  2966.  
  2967.  
  2968. static int
  2969. setClipTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
  2970. {
  2971.     if (scr->clip_title_pixel[index]!=scr->white_pixel &&
  2972.     scr->clip_title_pixel[index]!=scr->black_pixel) {
  2973.     wFreeColor(scr, scr->clip_title_pixel[index]);
  2974.     }
  2975.     scr->clip_title_pixel[index] = color->pixel;
  2976.  
  2977. #ifdef GRADIENT_CLIP_ARROW
  2978.     if (index == CLIP_NORMAL) {
  2979.     RImage *image;
  2980.     RColor color1, color2;
  2981.     int pt = CLIP_BUTTON_SIZE*wPreferences.icon_size/64;
  2982.     int as = pt - 15; /* 15 = 5+5+5 */
  2983.     
  2984.     FREE_PIXMAP(scr->clip_arrow_gradient);
  2985.  
  2986.     color1.red = (color->red >> 8)*6/10;
  2987.     color1.green = (color->green >> 8)*6/10;
  2988.     color1.blue = (color->blue >> 8)*6/10;
  2989.  
  2990.     color2.red = WMIN((color->red >> 8)*20/10, 255);
  2991.     color2.green = WMIN((color->green >> 8)*20/10, 255);
  2992.     color2.blue = WMIN((color->blue >> 8)*20/10, 255);
  2993.  
  2994.     image = RRenderGradient(as+1, as+1, &color1, &color2, RDiagonalGradient);
  2995.     RConvertImage(scr->rcontext, image, &scr->clip_arrow_gradient);
  2996.     RDestroyImage(image);
  2997.     }
  2998. #endif /* GRADIENT_CLIP_ARROW */
  2999.  
  3000.     return REFRESH_ICON_TITLE_COLOR;
  3001. }
  3002.  
  3003.  
  3004. static int
  3005. setWTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
  3006. {
  3007.     if (scr->window_title_pixel[index]!=scr->white_pixel &&
  3008.     scr->window_title_pixel[index]!=scr->black_pixel) {
  3009.     wFreeColor(scr, scr->window_title_pixel[index]);
  3010.     }
  3011.     
  3012.     scr->window_title_pixel[index] = color->pixel;
  3013.  
  3014.     if (index == WS_UNFOCUSED)
  3015.     XSetForeground(dpy, scr->info_text_gc, color->pixel);
  3016.     
  3017.     return REFRESH_WINDOW_TITLE_COLOR;
  3018. }
  3019.  
  3020.  
  3021. static int 
  3022. setMenuTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, long index)
  3023. {
  3024.     if (scr->menu_title_pixel[0]!=scr->white_pixel &&
  3025.     scr->menu_title_pixel[0]!=scr->black_pixel) {
  3026. #ifdef DRAWSTRING_PLUGIN
  3027.         if(!scr->drawstring_func[W_STRING_MTITLE])
  3028. #endif
  3029.     wFreeColor(scr, scr->menu_title_pixel[0]);
  3030.     }
  3031.     
  3032.     scr->menu_title_pixel[0] = color->pixel;
  3033.     XSetForeground(dpy, scr->menu_title_gc, color->pixel);
  3034.     
  3035.     return REFRESH_MENU_TITLE_COLOR;
  3036. }
  3037.  
  3038.  
  3039. static int 
  3040. setMenuTextColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  3041. {
  3042.     XGCValues gcv;
  3043. #define gcm (GCForeground|GCBackground|GCFillStyle)
  3044.  
  3045.     if (scr->mtext_pixel!=scr->white_pixel &&
  3046.     scr->mtext_pixel!=scr->black_pixel) {
  3047.     wFreeColor(scr, scr->mtext_pixel);
  3048.     }
  3049.     
  3050.     scr->mtext_pixel = color->pixel;
  3051.     
  3052.     XSetForeground(dpy, scr->menu_entry_gc, color->pixel);
  3053.  
  3054.  
  3055.     if (scr->dtext_pixel == scr->mtext_pixel) {
  3056.     gcv.foreground = scr->white_pixel;
  3057.     gcv.background = scr->black_pixel;
  3058.     gcv.fill_style = FillStippled;
  3059.     } else {
  3060.     gcv.foreground = scr->dtext_pixel;
  3061.     gcv.fill_style = FillSolid;
  3062.     }
  3063.     XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
  3064.     
  3065.     return REFRESH_MENU_COLOR;
  3066. #undef gcm
  3067. }
  3068.  
  3069.  
  3070. static int 
  3071. setMenuDisabledColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  3072. {
  3073.     XGCValues gcv;
  3074. #define gcm (GCForeground|GCBackground|GCFillStyle)
  3075.  
  3076.     if (scr->dtext_pixel!=scr->white_pixel &&
  3077.     scr->dtext_pixel!=scr->black_pixel) {
  3078.     wFreeColor(scr, scr->dtext_pixel);
  3079.     }
  3080.     
  3081.     scr->dtext_pixel = color->pixel;
  3082.  
  3083.     if (scr->dtext_pixel == scr->mtext_pixel) {
  3084.     gcv.foreground = scr->white_pixel;
  3085.     gcv.background = scr->black_pixel;
  3086.     gcv.fill_style = FillStippled;
  3087.     } else {
  3088.     gcv.foreground = scr->dtext_pixel;
  3089.     gcv.fill_style = FillSolid;
  3090.     }
  3091.     XChangeGC(dpy, scr->disabled_menu_entry_gc, gcm, &gcv);
  3092.  
  3093.     return REFRESH_MENU_COLOR;
  3094. #undef gcm
  3095. }
  3096.  
  3097. static int 
  3098. setIconTitleColor(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  3099. {
  3100.     XSetForeground(dpy, scr->icon_title_gc, color->pixel); 
  3101.     
  3102.     return REFRESH_ICON_TITLE_COLOR;
  3103. }
  3104.  
  3105.  
  3106. static int 
  3107. setIconTitleBack(WScreen *scr, WDefaultEntry *entry, XColor *color, void *foo)
  3108. {
  3109.     if (scr->icon_title_texture) {
  3110.     wTextureDestroy(scr, (WTexture*)scr->icon_title_texture);
  3111.     }
  3112.     XQueryColor (dpy, scr->w_colormap, color);
  3113.     scr->icon_title_texture = wTextureMakeSolid(scr, color);
  3114.     
  3115.     return REFRESH_ICON_TITLE_BACK;
  3116. }
  3117.  
  3118.  
  3119. static void
  3120. trackDeadProcess(pid_t pid, unsigned char status, WScreen *scr)
  3121. {
  3122.     close(scr->helper_fd);
  3123.     scr->helper_fd = 0;
  3124.     scr->helper_pid = 0;
  3125.     scr->flags.backimage_helper_launched = 0;
  3126. }    
  3127.  
  3128.  
  3129. static int
  3130. setWorkspaceSpecificBack(WScreen *scr, WDefaultEntry *entry, proplist_t value, 
  3131.              void *bar)
  3132. {
  3133.     int i;
  3134.     proplist_t val;
  3135.     char *str;
  3136.  
  3137.     if (scr->flags.backimage_helper_launched) {
  3138.     if (PLGetNumberOfElements(value)==0) {
  3139.         SendHelperMessage(scr, 'C', 0, NULL);
  3140.         SendHelperMessage(scr, 'K', 0, NULL);
  3141.  
  3142.         PLRelease(value);
  3143.         return 0;
  3144.     }
  3145.     } else {
  3146.     pid_t pid;
  3147.     int filedes[2];
  3148.  
  3149.     if (PLGetNumberOfElements(value) == 0)
  3150.         return 0;
  3151.     
  3152.     if (pipe(filedes) < 0) {
  3153.         wsyserror("pipe() failed:can't set workspace specific background image");
  3154.         
  3155.         PLRelease(value);
  3156.         return 0;
  3157.     }
  3158.  
  3159.     pid = fork();
  3160.     if (pid < 0) {
  3161.         wsyserror("fork() failed:can't set workspace specific background image");
  3162.         if (close(filedes[0]) < 0)
  3163.         wsyserror("could not close pipe");
  3164.         if (close(filedes[1]) < 0)
  3165.         wsyserror("could not close pipe");
  3166.  
  3167.     } else if (pid == 0) {
  3168.         SetupEnvironment(scr);
  3169.  
  3170.         if (close(0) < 0)
  3171.         wsyserror("could not close pipe");
  3172.         if (dup(filedes[0]) < 0) {
  3173.         wsyserror("dup() failed:can't set workspace specific background image");
  3174.         }
  3175.         if (wPreferences.smooth_workspace_back)
  3176.         execlp("wmsetbg", "wmsetbg", "-helper", "-S", "-d", NULL);
  3177.         else
  3178.         execlp("wmsetbg", "wmsetbg", "-helper", "-d", NULL);
  3179.         wsyserror("could not execute wmsetbg");
  3180.         exit(1);
  3181.     } else {
  3182.  
  3183.         if (fcntl(filedes[0], F_SETFD, FD_CLOEXEC) < 0) {
  3184.         wsyserror("error setting close-on-exec flag");
  3185.         }
  3186.         if (fcntl(filedes[1], F_SETFD, FD_CLOEXEC) < 0) {
  3187.         wsyserror("error setting close-on-exec flag");
  3188.         }
  3189.  
  3190.         scr->helper_fd = filedes[1];
  3191.         scr->helper_pid = pid;
  3192.         scr->flags.backimage_helper_launched = 1;
  3193.  
  3194.         wAddDeathHandler(pid, (WDeathHandler*)trackDeadProcess, scr);
  3195.  
  3196.         SendHelperMessage(scr, 'P', -1, wPreferences.pixmap_path);
  3197.     }
  3198.     
  3199.     }
  3200.  
  3201.     for (i = 0; i < PLGetNumberOfElements(value); i++) {
  3202.     val = PLGetArrayElement(value, i);
  3203.     if (val && PLIsArray(val) && PLGetNumberOfElements(val)>0) {
  3204.         str = PLGetDescription(val);
  3205.  
  3206.         SendHelperMessage(scr, 'S', i+1, str);
  3207.  
  3208.         free(str);
  3209.     } else {
  3210.         SendHelperMessage(scr, 'U', i+1, NULL);
  3211.     }
  3212.     }
  3213.     sleep(1);
  3214.  
  3215.     PLRelease(value);
  3216.     return 0;
  3217. }
  3218.  
  3219.  
  3220. static int
  3221. setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, proplist_t value, 
  3222.          void *bar)
  3223. {
  3224.     if (scr->flags.backimage_helper_launched) {
  3225.     char *str;
  3226.  
  3227.     if (PLGetNumberOfElements(value)==0) {
  3228.         SendHelperMessage(scr, 'U', 0, NULL);
  3229.     } else {
  3230.         /* set the default workspace background to this one */
  3231.         str = PLGetDescription(value);
  3232.         if (str) {
  3233.         SendHelperMessage(scr, 'S', 0, str);
  3234.         free(str);
  3235.         SendHelperMessage(scr, 'C', scr->current_workspace+1, NULL);
  3236.         } else {
  3237.         SendHelperMessage(scr, 'U', 0, NULL);
  3238.         }
  3239.     }
  3240.     } else {
  3241.     char *command;
  3242.     char *text;
  3243.  
  3244.     SetupEnvironment(scr);
  3245.     text = PLGetDescription(value);
  3246.     command = wmalloc(strlen(text)+40);
  3247.     if (wPreferences.smooth_workspace_back)
  3248.         sprintf(command, "wmsetbg -d -S -p '%s' &", text);
  3249.     else
  3250.         sprintf(command, "wmsetbg -d -p '%s' &", text);
  3251.     free(text);
  3252.     system(command);
  3253.     free(command);
  3254.     }
  3255.     PLRelease(value);
  3256.  
  3257.     return 0;
  3258. }
  3259.  
  3260.  
  3261. static int 
  3262. setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3263. {
  3264.     if (scr->widget_texture) {
  3265.     wTextureDestroy(scr, (WTexture*)scr->widget_texture);
  3266.     }
  3267.     scr->widget_texture = *(WTexSolid**)texture;
  3268.  
  3269.     return 0;
  3270. }
  3271.  
  3272.  
  3273. static int 
  3274. setFTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3275. {               
  3276.     if (scr->window_title_texture[WS_FOCUSED]) {
  3277.     wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
  3278.     }
  3279.     scr->window_title_texture[WS_FOCUSED] = *texture;
  3280.  
  3281.     return REFRESH_WINDOW_TEXTURES;
  3282. }
  3283.  
  3284.  
  3285. static int 
  3286. setPTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3287. {
  3288.     if (scr->window_title_texture[WS_PFOCUSED]) {
  3289.     wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
  3290.     }
  3291.     scr->window_title_texture[WS_PFOCUSED] = *texture;
  3292.     
  3293.     return REFRESH_WINDOW_TEXTURES;
  3294. }
  3295.  
  3296.  
  3297. static int 
  3298. setUTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3299. {
  3300.     if (scr->window_title_texture[WS_UNFOCUSED]) {
  3301.     wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
  3302.     }
  3303.     scr->window_title_texture[WS_UNFOCUSED] = *texture;
  3304.  
  3305.     return REFRESH_WINDOW_TEXTURES;
  3306. }
  3307.  
  3308.  
  3309. static int 
  3310. setResizebarBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3311. {
  3312.     if (scr->resizebar_texture[0]) {
  3313.     wTextureDestroy(scr, scr->resizebar_texture[0]);
  3314.     }
  3315.     scr->resizebar_texture[0] = *texture;
  3316.  
  3317.     return REFRESH_WINDOW_TEXTURES;
  3318. }
  3319.  
  3320.  
  3321. static int 
  3322. setMenuTitleBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3323. {
  3324.     if (scr->menu_title_texture[0]) {
  3325.     wTextureDestroy(scr, scr->menu_title_texture[0]);
  3326.     }
  3327.     scr->menu_title_texture[0] = *texture;
  3328.  
  3329.     return REFRESH_MENU_TITLE_TEXTURE;
  3330. }
  3331.  
  3332.  
  3333. static int 
  3334. setMenuTextBack(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo)
  3335. {
  3336.     if (scr->menu_item_texture) {
  3337.     wTextureDestroy(scr, scr->menu_item_texture);
  3338.     wTextureDestroy(scr, (WTexture*)scr->menu_item_auxtexture);
  3339.     }
  3340.     scr->menu_item_texture = *texture;
  3341.  
  3342.     scr->menu_item_auxtexture 
  3343.       = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
  3344.     
  3345.     return REFRESH_MENU_TEXTURE;
  3346. }
  3347.  
  3348.  
  3349. static int
  3350. setKeyGrab(WScreen *scr, WDefaultEntry *entry, WShortKey *shortcut, long index)
  3351. {
  3352.     WWindow *wwin;
  3353.     wKeyBindings[index] = *shortcut;
  3354.     
  3355.     wwin = scr->focused_window;
  3356.     
  3357.     while (wwin!=NULL) {
  3358.     XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
  3359.  
  3360.     if (!WFLAGP(wwin, no_bind_keys)) {
  3361.         wWindowSetKeyGrabs(wwin);
  3362.     }
  3363.     wwin = wwin->prev;
  3364.     }
  3365.     
  3366.     return 0;
  3367. }
  3368.  
  3369.  
  3370. static int
  3371. setIconPosition(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
  3372. {
  3373.     wArrangeIcons(scr, True);
  3374.  
  3375.     return 0;
  3376. }
  3377.  
  3378.  
  3379. static int
  3380. updateUsableArea(WScreen *scr, WDefaultEntry *entry, void *bar, void *foo)
  3381. {
  3382.     wScreenUpdateUsableArea(scr);
  3383.  
  3384.     return 0;
  3385. }
  3386.  
  3387.  
  3388. static int
  3389. setMenuStyle(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
  3390. {
  3391.     return REFRESH_MENU_TEXTURE;
  3392. }
  3393.  
  3394.  
  3395. /*
  3396. static int
  3397. setButtonImages(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
  3398. {
  3399.     return REFRESH_BUTTON_IMAGES;
  3400. }
  3401. */
  3402.  
  3403. /*
  3404.  * Very ugly kluge.
  3405.  * Need access to the double click variables, so that all widgets in
  3406.  * wmaker panels will have the same dbl-click values. 
  3407.  * TODO: figure a better way of dealing with it.
  3408.  */
  3409. #include "WINGsP.h"
  3410.  
  3411. static int
  3412. setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
  3413. {
  3414.     extern _WINGsConfiguration WINGsConfiguration;
  3415.  
  3416.     if (*value <= 0)
  3417.         *(int*)foo = 1;
  3418.  
  3419.     WINGsConfiguration.doubleClickDelay = *value;
  3420.     
  3421.     return 0;
  3422. }
  3423.  
  3424.  
  3425.  
  3426. static int
  3427. setMultiByte(WScreen *scr, WDefaultEntry *entry, char *value, void *foo)
  3428. {
  3429.     extern _WINGsConfiguration WINGsConfiguration;
  3430.  
  3431.     WINGsConfiguration.useMultiByte = *value;
  3432.     
  3433.     return 0;
  3434. }
  3435.  
  3436.  
  3437. #ifdef DEFINABLE_CURSOR
  3438. static int
  3439. setCursor(WScreen *scr, WDefaultEntry *entry, Cursor *cursor, long index)
  3440. {
  3441.    if (None != wCursor[index])
  3442.     {
  3443.        XFreeCursor(dpy, wCursor[index]);
  3444.     }
  3445.    
  3446.    wCursor[index] = *cursor;
  3447.  
  3448.    if ((WCUR_ROOT == index) && (None != *cursor))
  3449.     {
  3450.        XDefineCursor(dpy, scr->root_win, *cursor);
  3451.     }
  3452.  
  3453.    return 0;
  3454. }
  3455. #endif /* DEFINABLE_CURSOR*/
  3456.  
  3457.